diff --git a/.github/workflows/ccpp-mac.yml b/.github/workflows/ccpp-mac.yml index 9737ffa7fbc1ded8c3c7c22c143f2dee85650067..3324655c92dd41fa33685a37aca4c91415887e8b 100644 --- a/.github/workflows/ccpp-mac.yml +++ b/.github/workflows/ccpp-mac.yml @@ -3,7 +3,6 @@ name: C/C++ mac on: push: branches: - - "2.0" - master jobs: @@ -18,9 +17,9 @@ jobs: - name: git run: git submodule update --init --recursive - name: configure - run: mkdir build;cd build;cmake .. + run: mkdir build;cd build;cmake .. -DTARS_MYSQL=ON -DTARS_SSL=ON -DTARS_HTTP2=ON -DTARS_PROTOBUF=ON - name: make - run: cd build; make + run: cd build; make -j4 - name: make run run: cd build; make run-all diff --git a/.github/workflows/ccpp-win.yml b/.github/workflows/ccpp-win.yml index 417ef649a2e8bc9953ceaaaccf111207c148d8c0..499bf30be6d8f51c9a6a5e38e53da3a212a461d9 100644 --- a/.github/workflows/ccpp-win.yml +++ b/.github/workflows/ccpp-win.yml @@ -3,7 +3,6 @@ name: C/C++ win on: push: branches: - - "2.0" - master jobs: @@ -12,11 +11,16 @@ jobs: runs-on: windows-latest steps: + - name: Setup perl + uses: shogo82148/actions-setup-perl@v1 + with: + perl-version: ${{ matrix.perl }} + - run: perl -V - uses: actions/checkout@v2 - name: git run: git submodule update --init --recursive - name: configure - run: mkdir build;cd build; cmake --version; cmake .. -A X64 + run: mkdir build;cd build; cmake --version; cmake .. -A X64 -DTARS_MYSQL=ON -DTARS_PROTOBUF=ON - name: make run: cd build; cmake --build . --config release --target run-all diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 1877e19e7ccd4f004de801c7148b3fcdf0fcaa79..e65a57f929d1723eac419c2dcbd1d81311e0a314 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -3,7 +3,6 @@ name: C/C++ linux on: push: branches: - - "2.0" - master jobs: @@ -14,13 +13,13 @@ jobs: steps: - uses: actions/checkout@v2 - name: install - run: sudo apt-get install -y bison flex cmake; cmake --version + run: sudo apt-get install -y bison flex cmake psmisc libncurses5-dev zlib1g-dev; cmake --version - name: git run: git submodule update --init --recursive - name: configure - run: mkdir build;cd build;cmake .. + run: mkdir build;cd build;cmake .. -DTARS_MYSQL=ON -DTARS_SSL=ON -DTARS_HTTP2=ON -DTARS_PROTOBUF=ON - name: make - run: cd build; make + run: cd build; make -j4 - name: make run run: cd build; make run-all diff --git a/CMakeLists.txt b/CMakeLists.txt index 526e165d975d02d838724a0edc1dafaee02cfbea..ae88406b28c28f4f30d8778777fbb4ed59d682ce 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,14 +18,19 @@ if("${TARS_CPP_COMMON}" STREQUAL "") endif() +set(CLEAR_INCLUDE "clear-install.cmake") +FILE(WRITE ${CLEAR_INCLUDE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_INSTALL_PREFIX}/include)\n") +install(SCRIPT ${CLEAR_INCLUDE}) + #------------------------------------------------------------------- include_directories(${PROJECT_SOURCE_DIR}/util/include) + include_directories(${PROJECT_SOURCE_DIR}/servant) include_directories(${PROJECT_SOURCE_DIR}/servant/protocol) IF(WIN32) -include_directories(${CMAKE_SOURCE_DIR}/util/src/epoll_windows) +include_directories(${PROJECT_SOURCE_DIR}/util/src/epoll_windows) ENDIF() add_subdirectory(util) diff --git a/Changelist.md b/Changelist.md new file mode 100644 index 0000000000000000000000000000000000000000..36cca2362ad4397fe3d927adc1983fafe48e2738 --- /dev/null +++ b/Changelist.md @@ -0,0 +1,146 @@ +## v2.4.3 2020.06.10 +### en: +- tc_spin_lock support arm +- fix tc_http security problem +- fix tc_mysql table name with database name bug +- tarscpp create tars protocol, default package optional field +- fix tars2case 的bug + +### cn: +- tc_spin_lock 支持arm +- tc_http解析安全问题 +- tc_mysql 表名带db名称时 bug的问题 +- tarscpp协议缺省值默认打包 +- fix tars2case 的bug + +## v2.4.2 2020.06.02 +### en: +- Add English commet to some header file commet +- tars2case support json format +- fix tc_http bug, ignore last header line +- fix tc_json null bug and add interface +### cn: +- 部分头文件注释增加英文注释 +- tars2case支持json格式 +- 修复tc_http解析头, 漏掉最后一行的bug +- 修复tc_json null的bug 以及修改tc_json的函数接口, 更易用 + + +## v2.4.1 2020.05.06 +### en: +1 fix windows tars proto, define long bug, change to long long +2 fix windows, longlong tars_ntohll bug +3 fix windows, tc_ex system message pointer may be null cause crash +4 fix windows tc_epoll_server when send pending add epoll mod +### cn: +1 修复windows 64位 tars协议中, long 定义的问题(为32位,改成long long) +2 修复windows 64位整形, 字节序转换的问题 +3 修复windows tc_ex中系统消息指针为NULL的bug +4 修复windows windows tc_epoll_server when send pending add epoll mod + +## v2.4.0 2020.04.24 +### en: +- fix tars2json bug of array +- TC_EpollServer::Connction add _authInit initialize +- fix tarsnotify nodename bug +- compiler & install framework/*.tars in tarscpp +- fix tars-tools.cmake 'make tar' bug in linux +- In epoll server, change tc_cas_queue to tc_thread_queue +- tc_thread queue add front & pop_front +- add tars to xml support , add tc_xml.h/cpp tool class +- fix tc_json bug in float/double +- tars2cpp add interface to get/set sql +- TarsOutpuStream member change to public +- add tars2case for benchmark + +### cn: +- 修复tars2json中 array的bug +- TC_EpollServer::Connction 构造时,增加对_authInit变量初始化 +- 修复tarsnotify nodename bug +- compiler & install framework/*.tars in tarscpp +- 修复tars-tools.cmake make tar在linux的bug +- epoll server中tc_cas_queue改为 tc_thread_queue, tc_cas_queue在极端压力下可能会有问题, 原因待查 +- tc_thread queue add front & pop_front +- 增加tars to xml的支持, 增加tc_xml.h/cpp解析类 +- 修复tc_json的float/double的bug +- tars2cpp 工具增加将结构体转换成sql的接口 +- TarsOutpuStream成员变量改成public, 便于外部访问 +- 增加tars2case工具, 给benchmark工具使用 + +## v2.3.0 2020.04.02 +### en: +- modify cookies +- To support short connection (HTTP), servantproxy adds connection serial mode +- Support http1 client +- The interface of http1 and http2 is unified (http2 is not compatible before, and there are bugs in the previous design) +- Optimize HTTP performance +- Modify the file name and some class names at the beginning of tars to facilitate code merging +- Improve the logic of service IP list switching +### cn: +- cookies修改实现方式 +- 为支持短连接(http), ServantProxy增加连接串行模式 +- rpc支持http1客户端 +- 统一了http1 和 http2的接口(http2不在兼容之前的, 之前的设计上是有bug的) +优化http性能 +- 修改Tars开头的文件名以及部分类名, 方便代码合并 +- 改进服务ip list切换的逻辑 + +## v2.2.0 2020.04.02 +## en +- fix epoll bug in windows +## cn +- 修复epoll在windows下的bug + +## v2.1.2 2020.03.28 +### en: +- Fix bugs in tar-tools.cmake's support for make release +- cmake_tars_server.sh Permissions are automatically set to executable during installation +- fix tc_common::strto bug in unsigned char +- Download and compile curl automatically under windows to support the subsequent make upload +- Repair the support of tars-tools.cmake for make upload under Windows +### cn: +- 修复tars-tools.cmake对release支持的bug +- cmake_tars_server.sh等安装时权限都自动设置为可执行 +- tc_common::strto修复unsigned char的bug +- windows下自动下载编译curl,为后续make upload提供支持 +- 修复windows下tars-tools.cmake对make upload的支持 + +## v2.1.1 2020.03.23 +### en: +- update tars2node, support ts +- tc_json add get +- fix CMakeLists.txt in servant demo +### cn: +- 更新tars2node, 完善对ts的支持 +- tc_json增加一个api +- 修改了脚本创建服务后, CMakeLists.txt模板, 默认管理ssl http2 + +## v2.1.0 2020.03.14 +### en: +- udp in ipv6 bug +- add tars.resource +- fix rsp queue +- add max buffer limit, send queue, data accumulate clear +- Adjust cmake third library path +- tc_network_buffer add iterator +- optimize tc_http tc_http_async, improve http parser performance +- fix tars2node, support --with-tars +- remove rapidjson depends +### cn: +- 修改udp在ipv6下的bug +- 服务框架增加tars.resource命令字, 可以查看服务内网络连接细节 +- 修改响应队列上报的bug +- 增加发送buffer过载保护 +- 调整第三方库安装后的库路径 +- tc_network_buffer增加iterator接口 +- 优化tc_http tc_http tc_http_async性能, 提升http parser +f- ix tars2node, support --with-tars + +## v2.0.0 2020.03.03 +- support linux mac windows +- support ARM +- Reduce memory copy and improve performance +- Download compile dependencies automatically +- fix epoll server dead cycle bug +- Improve compilation mode and rely on MySQL client Lib +- fix some bug \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000000000000000000000000000000000000..4cefdbedf1f689d8ba0f10eb171b9b5ec80f99e9 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,157 @@ +# LICENSE + +Tencent is pleased to support the open source community by making Tars available. + +Copyright \(C\) 2016 THL A29 Limited, a Tencent company. All rights reserved. If you have downloaded a copy of the Tars binary from Tencent, please note that the Tars binary is licensed under the BSD 3-Clause License. + +If you have downloaded a copy of the Tars source code from Tencent, please note that Tars source code is licensed under the BSD 3-Clause License, except for the third-party components listed below which are subject to different license terms. Your integration of Tars into your own projects may require compliance with the BSD 3-Clause License, as well as the other licenses applicable to the third-party components included within Tars. + +A copy of the BSD 3-Clause License is included in this file. + +Other dependencies and licenses: + +## Open Source Software Licensed Under the Apache License, Version 2.0: + +1. Apache Tomcat 7.0.42 Copyright 1999-2013 The Apache Software Foundation +2. bootstrap-datepicker 1.7.0 Copyright 2012 Sebastien MALOT +3. grpc-java Copyright 2015 Google Inc. + +## Terms of the Apache License, Version 2.0: + +Apache License + +Version 2.0, January 2004 + +[http://www.apache.org/licenses/](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. + +1. 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. +2. 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. +3. 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. + +1. 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. +2. 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. +3. 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. +4. 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. +5. 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](http://www.apache.org/licenses/LICENSE-2.0) Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + +## Open Source Software Licensed Under the Boost Software License, Version 1.0: The below software in this distribution may have been modified by THL A29 Limited \("Tencent Modifications"\). All Tencent Modifications are Copyright \(C\) 2016 THL A29 Limited. + +1. Boost 1.53.0: + +\(1\) fcontext.hpp Copyright Oliver Kowalke 2009 + +\(2\) fcontext\_i386.hpp Copyright Oliver Kowalke 2009 + +\(3\) fcontext\_x86\_64.hpp Copyright Oliver Kowalke 2009 + +\(4\) jump\_i386\_sysv\_elf\_gas.S Copyright Oliver Kowalke 2009 + +\(5\) jump\_x86\_64\_sysv\_elf\_gas.S Copyright Oliver Kowalke 2009 + +\(6\) make\_i386\_sysv\_elf\_gas.S Copyright Oliver Kowalke 2009 + +\(7\) make\_x86\_64\_sysv\_elf\_gas.S Copyright Oliver Kowalke 2009 + +\(8\) tuple\_basic.hpp Copyright \(C\) 1999, 2000 Jaakko Jarvi \([jaakko.jarvi@cs.utu.fi](mailto:jaakko.jarvi@cs.utu.fi)\) + +## Terms of the Boost Software License, Version 1.0: + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license \(the "Software"\) to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. + +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, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +## Open Source Software Licensed Under the MIT License: + +1. jquery 1.9.1 Copyright 2012 jQuery Foundation and other contributors [http://jquery.com/](http://jquery.com/) +2. zTree 3.5.26 copyright \(c\) < hunter.z > +3. bootstrap 3.3.0 Copyright \(c\) 2011-2014 Twitter, Inc +4. bootstrap-table 1.11.0 Copyright \(c\) 2012-2016 Zhixin Wen [wenzhixin2010@gmail.com](mailto:wenzhixin2010@gmail.com) +5. Chart.js Copyright \(c\) 2013-2016 Nick Downie +6. mkdirp 0.5.0 Copyright 2010 James Halliday \([mail@substack.net](mailto:mail@substack.net)\) + +The below software \(7&8\) in this distribution may have been modified by THL A29 Limited \("Tencent Modifications"\). All Tencent Modifications are Copyright \(C\) 2016 THL A29 Limited. + +1. loki 0.1.7 Copyright \(c\) Andrei Alexandrescu, Jean-Francois Bastien, Guillaume Chatelet, Lukas Fittl, Fedor Pikus, Peter Kümmel, Rich Sposato +2. smhasher 0.150.1 Copyright \(c\) 2011 Austin Appleby \(Murmur3 routine\) Copyright \(c\) 2011 Patrick Hensley \(Python wrapper, packaging\) + +## Terms of the MIT License: + +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. + +Open Source Software Licensed Under the BSD 3-Clause License: + +## The below software in this distribution may have been modified by THL A29 Limited \("Tencent Modifications"\). All Tencent Modifications are Copyright \(C\) 2016 THL A29 Limited. + +1. gperftools 2.0 Copyright \(c\) 2005, Google Inc. All rights reserved. +2. Chrominum 56.0.2884.2 + +\(1\) bind.h Copyright \(c\) 2011 The Chromium Authors. All rights reserved. + +\(2\) bind\_internal.h Copyright \(c\) 2011 The Chromium Authors. All rights reserved. + +\(3\) callback.h Copyright \(c\) 2012 The Chromium Authors. All rights reserved. + +\(4\) callback\_internal.h Copyright \(c\) 2012 The Chromium Authors. All rights reserved. + +\(5\) callback\_internal.cc Copyright \(c\) 2012 The Chromium Authors. All rights reserved. + +## Terms of the BSD 3-Clause License: + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* 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. +* Neither the name of \[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. + diff --git a/README.md b/README.md index a2fa5395472c86998d8207453ba13ad714b8b697..597629d50fbba2d12d74e77aae71c52b7c353edc 100755 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ linux kernel: | 2.6.18 and above gcc: | 4.1.2 and above glibc-devel bison tool: | 2.5 and above flex tool: | 2.5 and above -cmake: | 2.8.8 and above +cmake: | 3.2 and above mysql: | 4.1.17 and above Compile and install @@ -33,4 +33,4 @@ make make install ``` -Detailed [reference](https://tarscloud.github.io/TarsDocs/an-li/tarscpp/README.en.html) +Detailed [reference](https://tarscloud.github.io/TarsDocs_en/) diff --git a/README.zh.md b/README.zh.md index 2a0b16de8bac59a61d9f21d84ef09fbdc7938b08..dd08325c5de0390c1d0f4c342f981ffcb2cc5cda 100755 --- a/README.zh.md +++ b/README.zh.md @@ -21,7 +21,7 @@ linux内核版本: | 2.6.18及以上版本 gcc版本: | 4.1.2及以上版本、glibc-devel bison工具版本: | 2.5及以上版本 flex工具版本: | 2.5及以上版本 -cmake版本: | 2.8.8及以上版本 +cmake版本: | 3.2及以上版本 mysql版本: | 4.1.17及以上版本 编译和安装 @@ -33,4 +33,4 @@ make make install ``` -详细安装参见[案例文档](https://tarscloud.github.io/TarsDocs/an-li/tarscpp/) +详细安装参见[案例文档](https://tarscloud.github.io/TarsDocs/) diff --git a/cmake/BuildTarsCpp.cmake b/cmake/BuildTarsCpp.cmake index 2531773186b7147794b93402bd8db879ac26a2a6..bdc7fd75d5a0bf8f1c2b56a5d436898ed9eb5884 100755 --- a/cmake/BuildTarsCpp.cmake +++ b/cmake/BuildTarsCpp.cmake @@ -66,6 +66,10 @@ macro(build_tars_server MODULE DEPS) target_link_libraries(${MODULE} ${LIB_HTTP2}) endif() + if(TARS_GPERF) + target_link_libraries(${MODULE} ${LIB_GPERF}) + endif(TARS_GPERF) + SET(MODULE-TGZ "${CMAKE_BINARY_DIR}/${MODULE}.tgz") SET(RUN_DEPLOY_COMMAND_FILE "${PROJECT_BINARY_DIR}/run-deploy-${MODULE}.cmake") FILE(WRITE ${RUN_DEPLOY_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/deploy/${MODULE})\n") diff --git a/cmake/Common.cmake b/cmake/Common.cmake index 6b5541801773991559daaa43a6d8eebd7d0ff931..359c63618b3207cafede5e9df6ca95f1819d01b6 100755 --- a/cmake/Common.cmake +++ b/cmake/Common.cmake @@ -1,5 +1,5 @@ -set(TARS_VERSION "2.0.0") +set(TARS_VERSION "2.4.3") add_definitions(-DTARS_VERSION="${TARS_VERSION}") set(CMAKE_VERBOSE_MAKEFILE off) @@ -14,24 +14,33 @@ ENDIF() set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) - -set(_USE_OPENTRACKING $ENV{_USE_OPENTRACKING}) -if(_USE_OPENTRACKING) -set(OPENTRACKING_INC "/usr/local/include") -add_definitions(-D_USE_OPENTRACKING=${_USE_OPENTRACKING}) -endif() +foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES}) + string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/lib) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/lib) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/bin) +endforeach() + +option(TARS_OPENTRACKING "option for open tracking" OFF) + +if (TARS_OPENTRACKING) + add_definitions(-DTARS_OPENTRACKING=1) + set(OPENTRACKING_INC "/usr/local/include") +endif () + +# set(TARS_OPENTRACKING $ENV{TARS_OPENTRACKING}) +# if(TARS_OPENTRACKING) +# set(OPENTRACKING_INC "/usr/local/include") +# add_definitions(-D_USE_OPENTRACKING=${TARS_OPENTRACKING}) +# endif() #------------------------------------------------------------- -if("${INSTALL_PREFIX}" STREQUAL "") - IF (UNIX) - set(INSTALL_PREFIX "/usr/local/tars/cpp") - ELSE() - set(INSTALL_PREFIX "c:\\tars\\cpp") - ENDIF() - - set(CMAKE_INSTALL_PREFIX ${INSTALL_PREFIX}) -endif() +IF (UNIX) + set(CMAKE_INSTALL_PREFIX "/usr/local/tars/cpp" CACHE STRING "set install path" FORCE) +ELSE() + set(CMAKE_INSTALL_PREFIX "c:\\tars\\cpp" CACHE STRING "set install path" FORCE) +ENDIF() #------------------------------------------------------------- IF (APPLE) @@ -66,7 +75,7 @@ IF (UNIX) ELSEIF (WIN32) set(PLATFORM "window") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4101 /wd4244 /wd4996 /wd4091 /wd4503 /wd4819 /wd4200 /wd4800 /wd4267 /wd4834") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4101 /wd4244 /wd4996 /wd4091 /wd4503 /wd4819 /wd4200 /wd4800 /wd4267 /wd4834 /wd4267") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /bigobj " ) ELSE () @@ -74,11 +83,7 @@ ELSE () ENDIF (UNIX) #------------------------------------------------------------- -IF(WIN32) -set(TARS2CPP "${CMAKE_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}/tars2cpp.exe") -ELSE() set(TARS2CPP "${CMAKE_BINARY_DIR}/bin/tars2cpp") -ENDIF() message("----------------------------------------------------") @@ -87,8 +92,10 @@ message("CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}") message("PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}") message("CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") message("PLATFORM: ${PLATFORM}") -message("INSTALL_PREFIX: ${INSTALL_PREFIX}") +message("CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}") message("BIN: ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") message("TARS2CPP: ${TARS2CPP}") +message("TARS_OPENTRACKING: ${TARS_OPENTRACKING}") + #------------------------------------------------------------- diff --git a/cmake/Thirdparty.cmake b/cmake/Thirdparty.cmake index f97c454856a23be6c6372a49db238f726c90aa72..f59626cdb3599ef8c5876d536cda73be3b85e1a7 100755 --- a/cmake/Thirdparty.cmake +++ b/cmake/Thirdparty.cmake @@ -1,17 +1,28 @@ -if (WIN32) - option(TARS_MYSQL "option for mysql" OFF) -else () - option(TARS_MYSQL "option for mysql" ON) -endif () - +option(TARS_MYSQL "option for mysql" ON) option(TARS_SSL "option for ssl" OFF) option(TARS_HTTP2 "option for http2" OFF) option(TARS_PROTOBUF "option for protocol" OFF) +option(TARS_GPERF "option for gperf" OFF) + +IF(UNIX) + FIND_PACKAGE(ZLIB) + IF(NOT ZLIB_FOUND) + SET(ERRORMSG "zlib library not found. Please install appropriate package, remove CMakeCache.txt and rerun cmake.") + IF(CMAKE_SYSTEM_NAME MATCHES "Linux") + SET(ERRORMSG ${ERRORMSG} "On Debian/Ubuntu, package name is zlib1g-dev(apt-get install zlib1g-dev), on Redhat/Centos and derivates it is zlib-devel (yum install zlib-devel).") + ENDIF() + MESSAGE(FATAL_ERROR ${ERRORMSG}) + ENDIF() + +ENDIF(UNIX) if (TARS_MYSQL) add_definitions(-DTARS_MYSQL=1) - set(TARS_SSL ON) +endif () + +if (TARS_GPERF) + add_definitions(-DTARS_GPERF=1) endif () if (TARS_SSL) @@ -35,90 +46,144 @@ set(LIB_HTTP2) set(LIB_SSL) set(LIB_CRYPTO) set(LIB_PROTOBUF) - +set(LIB_GTEST) #------------------------------------------------------------- add_custom_target(thirdparty) include(ExternalProject) +if (TARS_GPERF) + + set(GPERF_DIR_INC "${THIRDPARTY_PATH}/gpref/include") + set(GRPEF_DIR_LIB "${THIRDPARTY_PATH}/gpref/lib") + include_directories(${GPERF_DIR_INC}) + link_directories(${GRPEF_DIR_LIB}) + + if (UNIX) + set(LIB_GPERF "profiler") + + ExternalProject_Add(ADD_${LIB_GPERF} + URL https://tars-thirdpart-1300910346.cos.ap-guangzhou.myqcloud.com//src/gperftools-2.7.tar.gz + DOWNLOAD_DIR ${CMAKE_SOURCE_DIR}/download + PREFIX ${CMAKE_BINARY_DIR} + INSTALL_DIR ${CMAKE_SOURCE_DIR} + CONFIGURE_COMMAND ./configure --prefix=${CMAKE_BINARY_DIR}/src/gpref --disable-shared --disable-debugalloc + SOURCE_DIR ${CMAKE_BINARY_DIR}/src/gpref-lib + BUILD_IN_SOURCE 1 + BUILD_COMMAND make + # INSTALL_COMMAND ${CMAKE_COMMAND} --build . --config release --target install + URL_MD5 c6a852a817e9160c79bdb2d3101b4601 + ) + + add_dependencies(thirdparty ADD_${LIB_GPERF}) + + INSTALL(FILES ${CMAKE_BINARY_DIR}/src/gpref/bin/pprof + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ + DESTINATION thirdparty/bin/) + INSTALL(DIRECTORY ${CMAKE_BINARY_DIR}/src/gpref/lib DESTINATION thirdparty) + INSTALL(DIRECTORY ${CMAKE_BINARY_DIR}/src/gpref/include/gperftools DESTINATION thirdparty/include) + + endif (UNIX) + +endif (TARS_GPERF) + +set(LIB_GTEST "libgtest") + +if(WIN32) + ExternalProject_Add(ADD_CURL + URL http://cdn.tarsyun.com/src/curl-7.69.1.tar.gz + DOWNLOAD_DIR ${CMAKE_SOURCE_DIR}/download + PREFIX ${CMAKE_BINARY_DIR} + INSTALL_DIR ${CMAKE_SOURCE_DIR} + CONFIGURE_COMMAND ${CMAKE_COMMAND} . -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/src/curl + SOURCE_DIR ${CMAKE_BINARY_DIR}/src/curl-lib + BUILD_IN_SOURCE 1 + BUILD_COMMAND ${CMAKE_COMMAND} --build . --config release + INSTALL_COMMAND ${CMAKE_COMMAND} --build . --config release --target install + URL_MD5 b9bb5e11d579425154a9f97ed44be9b8 + ) + + add_dependencies(thirdparty ADD_CURL) + + INSTALL(DIRECTORY ${CMAKE_BINARY_DIR}/src/curl/ DESTINATION thirdparty) +endif(WIN32) + +if (WIN32) + + ExternalProject_Add(ADD_${LIB_GTEST} + URL http://cdn.tarsyun.com/src/release-1.10.0.zip + DOWNLOAD_DIR ${CMAKE_SOURCE_DIR}/download + PREFIX ${CMAKE_BINARY_DIR} + INSTALL_DIR ${CMAKE_SOURCE_DIR} + CONFIGURE_COMMAND ${CMAKE_COMMAND} . -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/src/gtest -Dgtest_force_shared_crt=ON + SOURCE_DIR ${CMAKE_BINARY_DIR}/src/gtest-lib + BUILD_IN_SOURCE 1 + BUILD_COMMAND ${CMAKE_COMMAND} --build . --config release + INSTALL_COMMAND ${CMAKE_COMMAND} --build . --config release --target install + URL_MD5 82358affdd7ab94854c8ee73a180fc53 + ) +else() + ExternalProject_Add(ADD_${LIB_GTEST} + URL http://cdn.tarsyun.com/src/release-1.10.0.tar.gz + DOWNLOAD_DIR ${CMAKE_SOURCE_DIR}/download + PREFIX ${CMAKE_BINARY_DIR} + INSTALL_DIR ${CMAKE_SOURCE_DIR} + CONFIGURE_COMMAND ${CMAKE_COMMAND} . -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/src/gtest + SOURCE_DIR ${CMAKE_BINARY_DIR}/src/gtest-lib + BUILD_IN_SOURCE 1 + BUILD_COMMAND make + URL_MD5 ecd1fa65e7de707cd5c00bdac56022cd + ) +endif() + +INSTALL(DIRECTORY ${CMAKE_BINARY_DIR}/src/gtest/ DESTINATION thirdparty) + +add_dependencies(thirdparty ADD_${LIB_GTEST}) if (TARS_PROTOBUF) set(PROTOBUF_DIR_INC "${THIRDPARTY_PATH}/protobuf/include") set(PROTOBUF_DIR_LIB "${THIRDPARTY_PATH}/protobuf/lib") + set(PROTOBUF_DIR_LIB64 "${THIRDPARTY_PATH}/protobuf/lib64") include_directories(${PROTOBUF_DIR_INC}) link_directories(${PROTOBUF_DIR_LIB}) + link_directories(${PROTOBUF_DIR_LIB64}) if (WIN32) set(LIB_PROTOC "libprotoc") set(LIB_PROTOBUF "libprotobuf") - SET(RUN_PROTOBUF_INSTALL_FILE "${PROJECT_BINARY_DIR}/run-protobuf-install.cmake") - FILE(WRITE ${RUN_PROTOBUF_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/protobuf)\n") - FILE(APPEND ${RUN_PROTOBUF_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/protobuf/lib)\n") - FILE(APPEND ${RUN_PROTOBUF_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/protobuf/include/google)\n") - FILE(APPEND ${RUN_PROTOBUF_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/protobuf-lib/${CMAKE_BUILD_TYPE}/libprotoc.dll ${CMAKE_BINARY_DIR}/src/protobuf/lib)\n") - FILE(APPEND ${RUN_PROTOBUF_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/protobuf-lib/${CMAKE_BUILD_TYPE}/libprotoc.lib ${CMAKE_BINARY_DIR}/src/protobuf/lib)\n") - FILE(APPEND ${RUN_PROTOBUF_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/protobuf-lib/${CMAKE_BUILD_TYPE}/libprotobuf.dll ${CMAKE_BINARY_DIR}/src/protobuf/lib)\n") - FILE(APPEND ${RUN_PROTOBUF_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/protobuf-lib/${CMAKE_BUILD_TYPE}/libprotobuf.lib ${CMAKE_BINARY_DIR}/src/protobuf/lib)\n") - FILE(APPEND ${RUN_PROTOBUF_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/protobuf-lib/${CMAKE_BUILD_TYPE}/protoc.exe ${CMAKE_BINARY_DIR}/src/protobuf/lib)\n") - FILE(APPEND ${RUN_PROTOBUF_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy_directory ${CMAKE_BINARY_DIR}/src/protobuf-lib/src/google ${CMAKE_BINARY_DIR}/src/protobuf/include/google)\n") - ExternalProject_Add(ADD_${LIB_PROTOBUF} URL http://cdn.tarsyun.com/src/protobuf-cpp-3.11.3.tar.gz + DOWNLOAD_DIR ${CMAKE_SOURCE_DIR}/download PREFIX ${CMAKE_BINARY_DIR} INSTALL_DIR ${CMAKE_SOURCE_DIR} - CONFIGURE_COMMAND cmake cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON + CONFIGURE_COMMAND ${CMAKE_COMMAND} cmake -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/src/protobuf -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON SOURCE_DIR ${CMAKE_BINARY_DIR}/src/protobuf-lib BUILD_IN_SOURCE 1 - BUILD_COMMAND cmake --build . --config release - LOG_CONFIGURE 1 - LOG_BUILD 1 - INSTALL_COMMAND cmake -P ${RUN_PROTOBUF_INSTALL_FILE} + BUILD_COMMAND ${CMAKE_COMMAND} --build . --config release + INSTALL_COMMAND ${CMAKE_COMMAND} --build . --config release --target install URL_MD5 fb59398329002c98d4d92238324c4187 ) - - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/protobuf/lib/libprotoc.dll DESTINATION lib) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/protobuf/lib/libprotoc.lib DESTINATION lib) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/protobuf/lib/libprotobuf.dll DESTINATION lib) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/protobuf/lib/libprotobuf.lib DESTINATION lib) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/protobuf/lib/protoc.exe DESTINATION bin) - else () set(LIB_PROTOC "protoc") set(LIB_PROTOBUF "protobuf") - SET(RUN_PROTOBUF_INSTALL_FILE "${PROJECT_BINARY_DIR}/run-protobuf-install.cmake") - FILE(WRITE ${RUN_PROTOBUF_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/protobuf)\n") - FILE(APPEND ${RUN_PROTOBUF_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/protobuf/lib)\n") - FILE(APPEND ${RUN_PROTOBUF_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/protobuf/bin)\n") - FILE(APPEND ${RUN_PROTOBUF_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/protobuf/include/google)\n") - FILE(APPEND ${RUN_PROTOBUF_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/protobuf-lib/libprotoc.a ${CMAKE_BINARY_DIR}/src/protobuf/lib)\n") - FILE(APPEND ${RUN_PROTOBUF_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/protobuf-lib/libprotobuf.a ${CMAKE_BINARY_DIR}/src/protobuf/lib)\n") - FILE(APPEND ${RUN_PROTOBUF_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/protobuf-lib/protoc ${CMAKE_BINARY_DIR}/src/protobuf/bin)\n") - FILE(APPEND ${RUN_PROTOBUF_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy_directory ${CMAKE_BINARY_DIR}/src/protobuf-lib/src/google ${CMAKE_BINARY_DIR}/src/protobuf/include/google)\n") - ExternalProject_Add(ADD_${LIB_PROTOBUF} URL http://cdn.tarsyun.com/src/protobuf-cpp-3.11.3.tar.gz + DOWNLOAD_DIR ${CMAKE_SOURCE_DIR}/download PREFIX ${CMAKE_BINARY_DIR} INSTALL_DIR ${CMAKE_SOURCE_DIR} - CONFIGURE_COMMAND cmake cmake -DBUILD_SHARED_LIBS=OFF + CONFIGURE_COMMAND ${CMAKE_COMMAND} cmake -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/src/protobuf -DBUILD_SHARED_LIBS=OFF SOURCE_DIR ${CMAKE_BINARY_DIR}/src/protobuf-lib BUILD_IN_SOURCE 1 BUILD_COMMAND make - LOG_CONFIGURE 1 - LOG_BUILD 1 - INSTALL_COMMAND cmake -P ${RUN_PROTOBUF_INSTALL_FILE} URL_MD5 fb59398329002c98d4d92238324c4187 ) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/protobuf/lib/libprotoc.a DESTINATION lib) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/protobuf/lib/libprotobuf.a DESTINATION lib) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/protobuf/bin/protoc DESTINATION bin) - endif () - INSTALL(DIRECTORY ${CMAKE_BINARY_DIR}/src/protobuf/include/google DESTINATION include) + INSTALL(DIRECTORY ${CMAKE_BINARY_DIR}/src/protobuf/ DESTINATION thirdparty) add_dependencies(thirdparty ADD_${LIB_PROTOBUF}) @@ -126,6 +191,7 @@ endif () if (TARS_SSL) + set(SSL_DIR "${THIRDPARTY_PATH}/openssl") set(SSL_DIR_INC "${THIRDPARTY_PATH}/openssl/include/") set(SSL_DIR_LIB "${THIRDPARTY_PATH}/openssl/lib") include_directories(${SSL_DIR_INC}) @@ -135,73 +201,37 @@ if (TARS_SSL) set(LIB_SSL "libssl") set(LIB_CRYPTO "libcrypto") - SET(RUN_SSL_INSTALL_FILE "${PROJECT_BINARY_DIR}/run-ssl-install.cmake") - FILE(WRITE ${RUN_SSL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/openssl)\n") - FILE(APPEND ${RUN_SSL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/openssl/lib)\n") - FILE(APPEND ${RUN_SSL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/openssl/include/openssl)\n") - FILE(APPEND ${RUN_SSL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/openssl-lib/libssl-1_1-x64.dll ${CMAKE_BINARY_DIR}/src/openssl/lib)\n") - FILE(APPEND ${RUN_SSL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/openssl-lib/libssl.lib ${CMAKE_BINARY_DIR}/src/openssl/lib)\n") - FILE(APPEND ${RUN_SSL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/openssl-lib/libssl_static.lib ${CMAKE_BINARY_DIR}/src/openssl/lib)\n") - FILE(APPEND ${RUN_SSL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/openssl-lib/libcrypto-1_1-x64.dll ${CMAKE_BINARY_DIR}/src/openssl/lib)\n") - FILE(APPEND ${RUN_SSL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/openssl-lib/libcrypto.lib ${CMAKE_BINARY_DIR}/src/openssl/lib)\n") - FILE(APPEND ${RUN_SSL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/openssl-lib/libcrypto_static.lib ${CMAKE_BINARY_DIR}/src/openssl/lib)\n") - FILE(APPEND ${RUN_SSL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy_directory ${CMAKE_BINARY_DIR}/src/openssl-lib/include/openssl ${CMAKE_BINARY_DIR}/src/openssl/include/openssl)\n") - ExternalProject_Add(ADD_${LIB_SSL} - DEPENDS ${LIB_ZLIB} URL http://cdn.tarsyun.com/src/openssl-1.1.1d.tar.gz + DOWNLOAD_DIR ${CMAKE_SOURCE_DIR}/download PREFIX ${CMAKE_BINARY_DIR} INSTALL_DIR ${CMAKE_SOURCE_DIR} CONFIGURE_COMMAND perl Configure --prefix=${CMAKE_BINARY_DIR}/src/openssl VC-WIN64A no-asm SOURCE_DIR ${CMAKE_BINARY_DIR}/src/openssl-lib BUILD_IN_SOURCE 1 BUILD_COMMAND nmake - LOG_CONFIGURE 1 - LOG_BUILD 1 - INSTALL_COMMAND cmake -P ${RUN_SSL_INSTALL_FILE} + INSTALL_COMMAND nmake install URL_MD5 3be209000dbc7e1b95bcdf47980a3baa ) - - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/openssl/lib/libssl-1_1-x64.dll DESTINATION lib) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/openssl/lib/libssl.lib DESTINATION lib) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/openssl/lib/libssl_static.lib DESTINATION lib) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/openssl/lib/libcrypto-1_1-x64.dll DESTINATION lib) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/openssl/lib/libcrypto.lib DESTINATION lib) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/openssl/lib/libcrypto_static.lib DESTINATION lib) - else () set(LIB_SSL "ssl") set(LIB_CRYPTO "crypto") - SET(RUN_SSL_INSTALL_FILE "${PROJECT_BINARY_DIR}/run-ssl-install.cmake") - FILE(WRITE ${RUN_SSL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/openssl)\n") - FILE(APPEND ${RUN_SSL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/openssl/lib)\n") - FILE(APPEND ${RUN_SSL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/openssl/include/openssl)\n") - FILE(APPEND ${RUN_SSL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/openssl-lib/libssl.a ${CMAKE_BINARY_DIR}/src/openssl/lib)\n") - FILE(APPEND ${RUN_SSL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/openssl-lib/libcrypto.a ${CMAKE_BINARY_DIR}/src/openssl/lib)\n") - FILE(APPEND ${RUN_SSL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy_directory ${CMAKE_BINARY_DIR}/src/openssl-lib/include/openssl ${CMAKE_BINARY_DIR}/src/openssl/include/openssl)\n") - ExternalProject_Add(ADD_${LIB_SSL} - DEPENDS ${LIB_ZLIB} URL http://cdn.tarsyun.com/src/openssl-1.1.1d.tar.gz + DOWNLOAD_DIR ${CMAKE_SOURCE_DIR}/download PREFIX ${CMAKE_BINARY_DIR} INSTALL_DIR ${CMAKE_SOURCE_DIR} CONFIGURE_COMMAND ./config --prefix=${CMAKE_BINARY_DIR}/src/openssl no-shared SOURCE_DIR ${CMAKE_BINARY_DIR}/src/openssl-lib BUILD_IN_SOURCE 1 BUILD_COMMAND make - LOG_CONFIGURE 1 - LOG_BUILD 1 - INSTALL_COMMAND cmake -P ${RUN_SSL_INSTALL_FILE} URL_MD5 3be209000dbc7e1b95bcdf47980a3baa ) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/openssl/lib/libssl.a DESTINATION lib) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/openssl/lib/libcrypto.a DESTINATION lib) - endif () - INSTALL(DIRECTORY ${CMAKE_BINARY_DIR}/src/openssl/include/openssl DESTINATION include) + INSTALL(DIRECTORY ${CMAKE_BINARY_DIR}/src/openssl/ DESTINATION thirdparty) add_dependencies(thirdparty ADD_${LIB_SSL}) endif () @@ -214,135 +244,93 @@ if (TARS_MYSQL) if (WIN32) set(LIB_MYSQL "libmysql") - SET(RUN_MYSQL_INSTALL_FILE "${PROJECT_BINARY_DIR}/run-mysql-install.cmake") - FILE(WRITE ${RUN_MYSQL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/mysql)\n") - FILE(APPEND ${RUN_MYSQL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/mysql/lib)\n") - FILE(APPEND ${RUN_MYSQL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/mysql/include)\n") - FILE(APPEND ${RUN_MYSQL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/mysql-lib/libmysql/${CMAKE_BUILD_TYPE}/libmysql.lib ${CMAKE_BINARY_DIR}/src/mysql/lib)\n") - FILE(APPEND ${RUN_MYSQL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/mysql-lib/libmysql/${CMAKE_BUILD_TYPE}/libmysql.dll ${CMAKE_BINARY_DIR}/src/mysql/lib)\n") - FILE(APPEND ${RUN_MYSQL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy_directory ${CMAKE_BINARY_DIR}/src/mysql-lib/include ${CMAKE_BINARY_DIR}/src/mysql/include)\n") ExternalProject_Add(ADD_${LIB_MYSQL} - URL http://cdn.tarsyun.com/src/mysql-5.6.46.zip - DEPENDS ADD_${LIB_SSL} + URL http://cdn.tarsyun.com/src/mysql-connector-c-6.1.11-src.zip + DOWNLOAD_DIR ${CMAKE_SOURCE_DIR}/download PREFIX ${CMAKE_BINARY_DIR} INSTALL_DIR ${CMAKE_SOURCE_DIR} - CONFIGURE_COMMAND cmake . -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/src/mysql -DBUILD_CONFIG=mysql_release -DWITH_SSL=${CMAKE_BINARY_DIR}/src/openssl + CONFIGURE_COMMAND ${CMAKE_COMMAND} . -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/src/mysql -DBUILD_CONFIG=mysql_release SOURCE_DIR ${CMAKE_BINARY_DIR}/src/mysql-lib BUILD_IN_SOURCE 1 - BUILD_COMMAND cmake --build . --config ${CMAKE_BUILD_TYPE} --target libmysql - LOG_CONFIGURE 1 - LOG_BUILD 1 - INSTALL_COMMAND cmake -P ${RUN_MYSQL_INSTALL_FILE} - URL_MD5 851be8973981979041ad422f7e5f693a + BUILD_COMMAND ${CMAKE_COMMAND} --build . --config release + INSTALL_COMMAND ${CMAKE_COMMAND} --build . --config release --target install + URL_MD5 62de01beffc48348708c983a585b4dc1 ) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/mysql/lib/libmysql.lib DESTINATION lib) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/mysql/lib/libmysql.dll DESTINATION lib) - else () set(LIB_MYSQL "mysqlclient") - SET(RUN_MYSQL_INSTALL_FILE "${PROJECT_BINARY_DIR}/run-mysql-install.cmake") - FILE(WRITE ${RUN_MYSQL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/mysql)\n") - FILE(APPEND ${RUN_MYSQL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/mysql/lib)\n") - FILE(APPEND ${RUN_MYSQL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/mysql/include)\n") - FILE(APPEND ${RUN_MYSQL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/mysql-lib/libmysql/libmysqlclient.a ${CMAKE_BINARY_DIR}/src/mysql/lib)\n") - FILE(APPEND ${RUN_MYSQL_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy_directory ${CMAKE_BINARY_DIR}/src/mysql-lib/include ${CMAKE_BINARY_DIR}/src/mysql/include)\n") - ExternalProject_Add(ADD_${LIB_MYSQL} - URL http://cdn.tarsyun.com/src/mysql-5.6.26.tar.gz + URL http://cdn.tarsyun.com/src/mysql-connector-c-6.1.11-src.tar.gz + DOWNLOAD_DIR ${CMAKE_SOURCE_DIR}/download PREFIX ${CMAKE_BINARY_DIR} INSTALL_DIR ${CMAKE_SOURCE_DIR} - CONFIGURE_COMMAND cmake . -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DDISABLE_SHARED=1 + CONFIGURE_COMMAND ${CMAKE_COMMAND} . -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/src/mysql -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DDISABLE_SHARED=1 SOURCE_DIR ${CMAKE_BINARY_DIR}/src/mysql-lib BUILD_IN_SOURCE 1 BUILD_COMMAND make mysqlclient - LOG_CONFIGURE 1 - LOG_BUILD 1 - INSTALL_COMMAND cmake -P ${RUN_MYSQL_INSTALL_FILE} - URL_MD5 c537c08c1276abc79d76e8e562bbcea5 - #URL_MD5 9d225528742c882d5b1e4a40b0877690 + URL_MD5 98ca2071f9d4c6b73146cc0455f6b914 ) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/mysql/lib/libmysqlclient.a DESTINATION lib) - endif () - INSTALL(DIRECTORY ${CMAKE_BINARY_DIR}/src/mysql/include/mysql DESTINATION include) + INSTALL(DIRECTORY ${CMAKE_BINARY_DIR}/src/mysql/lib DESTINATION thirdparty) + INSTALL(DIRECTORY ${CMAKE_BINARY_DIR}/src/mysql/include/ DESTINATION thirdparty/include/mysql) add_dependencies(thirdparty ADD_${LIB_MYSQL}) - endif () + if (TARS_HTTP2) set(NGHTTP2_DIR_INC "${THIRDPARTY_PATH}/nghttp2/include/") set(NGHTTP2_DIR_LIB "${THIRDPARTY_PATH}/nghttp2/lib") + set(NGHTTP2_DIR_LIB64 "${THIRDPARTY_PATH}/nghttp2/lib64") include_directories(${NGHTTP2_DIR_INC}) link_directories(${NGHTTP2_DIR_LIB}) + link_directories(${NGHTTP2_DIR_LIB64}) - if (WIN32) - set(LIB_HTTP2 "nghttp2_static") - SET(RUN_HTTP2_INSTALL_FILE "${PROJECT_BINARY_DIR}/run-http2-install.cmake") - FILE(WRITE ${RUN_HTTP2_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/nghttp2)\n") - FILE(APPEND ${RUN_HTTP2_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/nghttp2/lib)\n") - FILE(APPEND ${RUN_HTTP2_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/nghttp2/include/nghttp2)\n") - FILE(APPEND ${RUN_HTTP2_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/nghttp2-lib/lib/${CMAKE_BUILD_TYPE}/nghttp2_static.lib ${CMAKE_BINARY_DIR}/src/nghttp2/lib)\n") - FILE(APPEND ${RUN_HTTP2_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy_directory ${CMAKE_BINARY_DIR}/src/nghttp2-lib/lib/includes/nghttp2 ${CMAKE_BINARY_DIR}/src/nghttp2/include/nghttp2)\n") + set(LIB_HTTP2 "nghttp2_static") + if (WIN32) ExternalProject_Add(ADD_${LIB_HTTP2} URL http://cdn.tarsyun.com/src/nghttp2-1.40.0.tar.gz + DOWNLOAD_DIR ${CMAKE_SOURCE_DIR}/download PREFIX ${CMAKE_BINARY_DIR} INSTALL_DIR ${CMAKE_SOURCE_DIR} - CONFIGURE_COMMAND cmake . -DENABLE_SHARED_LIB=OFF -DENABLE_STATIC_LIB=ON -DENABLE_LIB_ONLY=ON + CONFIGURE_COMMAND ${CMAKE_COMMAND} . -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/src/nghttp2 -DENABLE_LIB_ONLY=ON -DENABLE_STATIC_LIB=ON SOURCE_DIR ${CMAKE_BINARY_DIR}/src/nghttp2-lib BUILD_IN_SOURCE 1 - LOG_BUILD 1 - LOG_CONFIGURE 1 - BUILD_COMMAND cmake --build . --config release - INSTALL_COMMAND cmake -P ${RUN_HTTP2_INSTALL_FILE} + BUILD_COMMAND ${CMAKE_COMMAND} --build . --config release + INSTALL_COMMAND ${CMAKE_COMMAND} --build . --config release --target install URL_MD5 5df375bbd532fcaa7cd4044b54b1188d ) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/nghttp2/lib/nghttp2_static.lib DESTINATION lib) - else () - set(LIB_HTTP2 "nghttp2_static") - SET(RUN_HTTP2_INSTALL_FILE "${PROJECT_BINARY_DIR}/run-http2-install.cmake") - FILE(WRITE ${RUN_HTTP2_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/nghttp2)\n") - FILE(APPEND ${RUN_HTTP2_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/nghttp2/lib)\n") - FILE(APPEND ${RUN_HTTP2_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/src/nghttp2/include/nghttp2)\n") - FILE(APPEND ${RUN_HTTP2_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy ${CMAKE_BINARY_DIR}/src/nghttp2-lib/lib/libnghttp2_static.a ${CMAKE_BINARY_DIR}/src/nghttp2/lib)\n") - FILE(APPEND ${RUN_HTTP2_INSTALL_FILE} "EXECUTE_PROCESS(COMMAND cmake -E copy_directory ${CMAKE_BINARY_DIR}/src/nghttp2-lib/lib/includes/nghttp2 ${CMAKE_BINARY_DIR}/src/nghttp2/include/nghttp2)\n") - ExternalProject_Add(ADD_${LIB_HTTP2} URL http://cdn.tarsyun.com/src/nghttp2-1.40.0.tar.gz + DOWNLOAD_DIR ${CMAKE_SOURCE_DIR}/download PREFIX ${CMAKE_BINARY_DIR} INSTALL_DIR ${CMAKE_SOURCE_DIR} - CONFIGURE_COMMAND cmake . -DENABLE_SHARED_LIB=OFF -DENABLE_STATIC_LIB=ON -DENABLE_LIB_ONLY=ON + CONFIGURE_COMMAND ${CMAKE_COMMAND} . -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/src/nghttp2 -DENABLE_LIB_ONLY=ON -DENABLE_STATIC_LIB=ON SOURCE_DIR ${CMAKE_BINARY_DIR}/src/nghttp2-lib BUILD_IN_SOURCE 1 - LOG_BUILD 1 - LOG_CONFIGURE 1 BUILD_COMMAND make - INSTALL_COMMAND cmake -P ${RUN_HTTP2_INSTALL_FILE} URL_MD5 5df375bbd532fcaa7cd4044b54b1188d ) - INSTALL(FILES ${CMAKE_BINARY_DIR}/src/nghttp2/lib/libnghttp2_static.a DESTINATION lib) - endif () - INSTALL(DIRECTORY ${CMAKE_BINARY_DIR}/src/nghttp2/include/nghttp2 DESTINATION include) + INSTALL(DIRECTORY ${CMAKE_BINARY_DIR}/src/nghttp2/ DESTINATION thirdparty) add_dependencies(thirdparty ADD_${LIB_HTTP2}) -endif () +endif () message("----------------------------------------------------") message("TARS_MYSQL: ${TARS_MYSQL}") message("TARS_HTTP2: ${TARS_HTTP2}") message("TARS_SSL: ${TARS_SSL}") message("TARS_PROTOBUF: ${TARS_PROTOBUF}") - +message("TARS_GPERF: ${TARS_GPERF}") diff --git a/examples/AuthDemo/Client/config.conf b/examples/AuthDemo/Client/config.conf index 5a8d9c72678e849b6bac76625a62aa72d3e92636..d616e568f809efc839669dbbfebd1297974e7dd3 100755 --- a/examples/AuthDemo/Client/config.conf +++ b/examples/AuthDemo/Client/config.conf @@ -28,12 +28,6 @@ accesskey = tars-test-user #auth secret key secretkey = 123456 - #server crt - ca = ../examples/SSLDemo/certs/server.crt - #can be empty - cert = ../examples/SSLDemo/certs/client.crt - #can be empty - key = ../examples/SSLDemo/certs/client.key diff --git a/examples/AuthDemo/Client/main.cpp b/examples/AuthDemo/Client/main.cpp index 1adc18e84945c7f00c97cc37e9394e93b145f162..7dd8af1592f319a4c2ff6542cf957acba6c8c316 100644 --- a/examples/AuthDemo/Client/main.cpp +++ b/examples/AuthDemo/Client/main.cpp @@ -153,7 +153,7 @@ int main(int argc, char *argv[]) conf.parseFile(option.getValue("config")); _comm->setProperty(conf); -// TarsRollLogger::getInstance()->logger()->setLogLevel(6); +// LocalRollLogger::getInstance()->logger()->setLogLevel(6); _comm->setProperty("sendqueuelimit", "1000000"); _comm->setProperty("asyncqueuecap", "1000000"); diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 36fd4c1689f7d189a830f876babc5851af20d5eb..e8047b9ae912ce5a4c1f66be256ba43658c0eb75 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -12,179 +12,195 @@ endif() add_subdirectory(PushDemo) add_subdirectory(QuickStartDemo) add_subdirectory(StressDemo) +add_subdirectory(UdpDemo) + +set(WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) if(WIN32) add_custom_target(run-quick-start - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} DEPENDS QuickStartDemo QuickStartDemoClient USES_TERMINAL - COMMAND examples/scripts/run-quick-start.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND ../examples/scripts/run-quick-start.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call quick start") add_custom_target(run-http - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} DEPENDS HttpServer HttpClient USES_TERMINAL - COMMAND examples/scripts/run-http.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND ../examples/scripts/run-http.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run http") add_custom_target(run-auth - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} DEPENDS AuthServer AuthClient USES_TERMINAL - COMMAND examples/scripts/run-auth.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND ../examples/scripts/run-auth.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run auth") + add_custom_target(run-udp + WORKING_DIRECTORY ${WORKING_DIRECTORY} + DEPENDS UdpServer UdpClient + USES_TERMINAL + COMMAND ../examples/scripts/run-udp.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMENT "call run udp") + if(TARS_HTTP2) add_custom_target(run-http2 - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} DEPENDS Http2Server Http2Client USES_TERMINAL - COMMAND examples/scripts/run-http2.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND ../examples/scripts/run-http2.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run http2") endif() if(TARS_SSL) add_custom_target(run-ssl - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} DEPENDS SSLServer SSLClient USES_TERMINAL - COMMAND examples/scripts/run-ssl.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND ../examples/scripts/run-ssl.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run ssl") endif() add_custom_target(run-co - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} DEPENDS CoroutineDemoAServer CoroutineDemoBServer CoroutineDemoClient testCoro testParallelCoro USES_TERMINAL - COMMAND examples/scripts/run-co.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND ../examples/scripts/run-co.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run co") add_custom_target(run-custom - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} DEPENDS CustomServer CustomClient USES_TERMINAL - COMMAND examples/scripts/run-custom.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND ../examples/scripts/run-custom.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run custom") add_custom_target(run-push - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} DEPENDS PushServer PushClient USES_TERMINAL - COMMAND examples/scripts/run-push.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND ../examples/scripts/run-push.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run push") if(TARS_SSL) add_custom_target(run-all - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} DEPENDS QuickStartDemo QuickStartDemoClient HttpServer HttpClient AuthServer AuthClient SSLServer SSLClient CoroutineDemoAServer CoroutineDemoBServer CoroutineDemoClient testCoro testParallelCoro PushServer PushClient USES_TERMINAL - COMMAND examples/scripts/run-quick-start.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMAND examples/scripts/run-http.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMAND examples/scripts/run-co.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMAND examples/scripts/run-push.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMAND examples/scripts/run-auth.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMAND examples/scripts/run-ssl.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND ../examples/scripts/run-quick-start.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMAND ../examples/scripts/run-http.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMAND ../examples/scripts/run-co.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMAND ../examples/scripts/run-push.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMAND ../examples/scripts/run-auth.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMAND ../examples/scripts/run-ssl.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run all") else() add_custom_target(run-all - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} USES_TERMINAL DEPENDS QuickStartDemo QuickStartDemoClient HttpServer HttpClient AuthServer AuthClient CoroutineDemoAServer CoroutineDemoBServer CoroutineDemoClient testCoro testParallelCoro PushServer PushClient - COMMAND examples/scripts/run-quick-start.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMAND examples/scripts/run-http.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMAND examples/scripts/run-co.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMAND examples/scripts/run-push.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMAND examples/scripts/run-auth.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND ../examples/scripts/run-quick-start.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMAND ../examples/scripts/run-http.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMAND ../examples/scripts/run-co.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMAND ../examples/scripts/run-push.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMAND ../examples/scripts/run-auth.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run all") endif() add_custom_target(run-kill - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} USES_TERMINAL - COMMAND examples/scripts/run-kill.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND ../examples/scripts/run-kill.bat ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run kill") else(WIN32) add_custom_target(run-quick-start - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} DEPENDS QuickStartDemo QuickStartDemoClient - COMMAND sh examples/scripts/run-quick-start.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND sh ../examples/scripts/run-quick-start.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call quick start") add_custom_target(run-http - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - DEPENDS HttpServer HttpClient - COMMAND sh examples/scripts/run-http.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMENT "call run http") + WORKING_DIRECTORY ${WORKING_DIRECTORY} + DEPENDS HttpServer HttpClient + COMMAND sh ../examples/scripts/run-http.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMENT "call run http") + + add_custom_target(run-udp + WORKING_DIRECTORY ${WORKING_DIRECTORY} + DEPENDS UdpServer UdpClient + COMMAND sh ../examples/scripts/run-udp.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMENT "call run udp") add_custom_target(run-auth - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} DEPENDS AuthServer AuthClient - COMMAND sh examples/scripts/run-auth.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND sh ../examples/scripts/run-auth.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run auth") if(TARS_HTTP2) add_custom_target(run-http2 - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} DEPENDS Http2Server Http2Client - COMMAND sh examples/scripts/run-http2.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND sh ../examples/scripts/run-http2.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run http2") endif() if(TARS_SSL) add_custom_target(run-ssl - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} DEPENDS SSLServer SSLClient - COMMAND sh examples/scripts/run-ssl.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND sh ../examples/scripts/run-ssl.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run ssl") endif() add_custom_target(run-co - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} DEPENDS CoroutineDemoAServer CoroutineDemoBServer CoroutineDemoClient testCoro testParallelCoro - COMMAND sh examples/scripts/run-co.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND sh ../examples/scripts/run-co.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run co") add_custom_target(run-custom - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} DEPENDS CustomServer CustomClient - COMMAND sh examples/scripts/run-custom.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND sh ../examples/scripts/run-custom.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run custom") add_custom_target(run-push - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} DEPENDS PushServer PushClient - COMMAND sh examples/scripts/run-push.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND sh ../examples/scripts/run-push.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run push") if(TARS_SSL) add_custom_target(run-all - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} DEPENDS QuickStartDemo QuickStartDemoClient HttpServer HttpClient AuthServer AuthClient SSLServer SSLClient CoroutineDemoAServer CoroutineDemoBServer CoroutineDemoClient testCoro testParallelCoro PushServer PushClient - COMMAND sh examples/scripts/run-quick-start.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMAND sh examples/scripts/run-http.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMAND sh examples/scripts/run-co.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMAND sh examples/scripts/run-push.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMAND sh examples/scripts/run-auth.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMAND sh examples/scripts/run-ssl.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND sh ../examples/scripts/run-quick-start.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMAND sh ../examples/scripts/run-http.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMAND sh ../examples/scripts/run-co.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMAND sh ../examples/scripts/run-push.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMAND sh ../examples/scripts/run-auth.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMAND sh ../examples/scripts/run-ssl.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run all") else() add_custom_target(run-all - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} DEPENDS QuickStartDemo QuickStartDemoClient HttpServer HttpClient AuthServer AuthClient CoroutineDemoAServer CoroutineDemoBServer CoroutineDemoClient testCoro testParallelCoro PushServer PushClient - COMMAND sh examples/scripts/run-quick-start.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMAND sh examples/scripts/run-http.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMAND sh examples/scripts/run-co.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMAND sh examples/scripts/run-push.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} - COMMAND sh examples/scripts/run-auth.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + COMMAND sh ../examples/scripts/run-quick-start.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMAND sh ../examples/scripts/run-http.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMAND sh ../examples/scripts/run-co.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMAND sh ../examples/scripts/run-push.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} + COMMAND sh ../examples/scripts/run-auth.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run all") endif() add_custom_target(run-kill - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - COMMAND sh examples/scripts/run-kill.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${WORKING_DIRECTORY} + COMMAND sh ../examples/scripts/run-kill.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${WORKING_DIRECTORY} COMMENT "call run kill") -endif(WIN32) \ No newline at end of file +endif(WIN32) diff --git a/examples/CoroutineDemo/client/main.cpp b/examples/CoroutineDemo/client/main.cpp index 2242333225095f077fb79f02969228ebb14b4deb..22cc4e65e506c72e9a88bb467d39e134a2531a8d 100644 --- a/examples/CoroutineDemo/client/main.cpp +++ b/examples/CoroutineDemo/client/main.cpp @@ -188,7 +188,7 @@ int main(int argc, char *argv[]) param.pPrx = _comm->stringToProxy(coroObj); -// TarsRollLogger::getInstance()->logger()->setLogLevel(6); +// LocalRollLogger::getInstance()->logger()->setLogLevel(6); _comm->setProperty("sendqueuelimit", "1000000"); _comm->setProperty("asyncqueuecap", "1000000"); diff --git a/examples/CustomDemo/CustomClient/main.cpp b/examples/CustomDemo/CustomClient/main.cpp index d27fe0653b29f8b0db15b919bfe4639a152876e1..c999639227c599faaa4bdcc5e07549f45f4c81ed 100644 --- a/examples/CustomDemo/CustomClient/main.cpp +++ b/examples/CustomDemo/CustomClient/main.cpp @@ -198,7 +198,7 @@ int main(int argc, char *argv[]) param.servantPrx = _comm->stringToProxy(sObjName); -// TarsRollLogger::getInstance()->logger()->setLogLevel(6); +// LocalRollLogger::getInstance()->logger()->setLogLevel(6); ProxyProtocol prot; prot.requestFunc = customRequest; prot.responseFunc = customResponse; diff --git a/examples/HttpDemo/Http2Client/main.cpp b/examples/HttpDemo/Http2Client/main.cpp index 2344d50472773ea21baa484953dd21e6e630eeec..8123fe3898b63ba1b41dc039d0e9570ea18b94d0 100644 --- a/examples/HttpDemo/Http2Client/main.cpp +++ b/examples/HttpDemo/Http2Client/main.cpp @@ -45,25 +45,26 @@ void syncRpc2(int c) { int64_t t = TC_Common::now2us(); - std::map header; - header[":authority"] = "domain.com"; - header[":scheme"] = "http"; - // header[":method"] = "POST"; - - std::map rheader; //发起远程调用 for (int i = 0; i < c; ++i) { - string rbody; + shared_ptr rsp; + shared_ptr req = std::make_shared(); + req->setPostRequest("http://domain.com/hello", string("helloworld-") + TC_Common::tostr(i), true); + + try + { + param.servant2Prx->http_call("hello", req, rsp); + } + catch (exception & e) + { + cout << "exception:" << e.what() << endl; + } + + assert(req->getContent() == rsp->getContent()); + assert(req.use_count() == 1); + assert(rsp.use_count() == 1); - try - { - param.servant2Prx->http_call("POST", "/", header, "helloworld", rheader, rbody); - } - catch(exception& e) - { - cout << "exception:" << e.what() << endl; - } ++callback_count; } @@ -71,30 +72,22 @@ void syncRpc2(int c) cout << "syncRpc2 total:" << cost << "us, avg:" << 1.*cost/c << "us" << endl; } - struct TestHttpCallback : public HttpCallback { - TestHttpCallback(int64_t t, int i, int c) : start(t), cur(i), count(c) + TestHttpCallback(const string &buff) : _buff(buff) { } - virtual int onHttpResponse(const std::map& requestHeaders , - const std::map& responseHeaders , - const std::vector& rspBody) + virtual int onHttpResponse(const shared_ptr &rsp) { callback_count++; - if(cur == count-1) - { - int64_t cost = TC_Common::now2us() - start; - cout << "onHttpResponse count:" << count << ", " << cost << " us, avg:" << 1.*cost/count << "us" << endl; - } + assert(_buff == rsp->getContent()); return 0; } - virtual int onHttpResponseException(const std::map& requestHeaders, - int expCode) + virtual int onHttpResponseException(int expCode) { cout << "onHttpResponseException expCode:" << expCode << endl; @@ -103,27 +96,26 @@ struct TestHttpCallback : public HttpCallback return 0; } - int64_t start; - int cur; - int count; + string _buff; }; void asyncRpc2(int c) { int64_t t = TC_Common::now2us(); - std::map header; - header[":authority"] = "domain.com"; - header[":scheme"] = "http"; - //发起远程调用 for (int i = 0; i < c; ++i) { - HttpCallbackPtr p = new TestHttpCallback(t, i, c); + shared_ptr req = std::make_shared(); + + string buff = string("helloworld-") + TC_Common::tostr(i); + req->setPostRequest("http://domain.com/hello", buff, true); + + HttpCallbackPtr p = new TestHttpCallback(buff); try { - param.servant2Prx->http_call_async("POST", "/", header, "helloworld", p); + param.servant2Prx->http_call_async("hello", req, p); } catch(exception& e) { @@ -140,6 +132,7 @@ void asyncRpc2(int c) cout << "asyncRpc2 send:" << cost << "us, avg:" << 1.*cost/c << "us" << endl; } + int main(int argc, char *argv[]) { try @@ -173,11 +166,7 @@ int main(int argc, char *argv[]) param.servant2Prx->tars_connect_timeout(5000); param.servant2Prx->tars_async_timeout(60*1000); - ProxyProtocol proto; - - proto.requestFunc = ProxyProtocol::http2Request; - proto.responseFunc = ProxyProtocol::http2Response; - param.servant2Prx->tars_set_protocol(proto); + param.servant2Prx->tars_set_protocol(ServantProxy::PROTOCOL_HTTP2); int64_t start = TC_Common::now2us(); diff --git a/examples/HttpDemo/Http2Server/Http2Imp.cpp b/examples/HttpDemo/Http2Server/Http2Imp.cpp index 823e19eebf7b77cceb486249003d709d47460454..9ef4537098b0979b803b918df6cafddf1e3495c7 100644 --- a/examples/HttpDemo/Http2Server/Http2Imp.cpp +++ b/examples/HttpDemo/Http2Server/Http2Imp.cpp @@ -57,6 +57,8 @@ int Http2Imp::doRequest(TarsCurrentPtr current, vector &buffer) { cout << "encodeResponse error:" << session->getErrMsg() << endl; } +// cout << context->request.getContent() << endl; + buffer.insert(buffer.end(), data.begin(), data.end()); } diff --git a/examples/HttpDemo/HttpClient/main.cpp b/examples/HttpDemo/HttpClient/main.cpp index 5b250deaaac20fac314b81b32258e45bc1608713..25289970971b88d396dd524948cd32318b0e910c 100644 --- a/examples/HttpDemo/HttpClient/main.cpp +++ b/examples/HttpDemo/HttpClient/main.cpp @@ -1,38 +1,23 @@ -/** - * Tencent is pleased to support the open source community by making Tars available. - * - * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * Unless required by applicable law or agreed to in writing, software distributed - * under the License is distributed on an "AS IS" BASIS, WITHOUT 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 "util/tc_http.h" -#include "util/tc_option.h" #include "util/tc_common.h" #include "util/tc_clientsocket.h" #include "util/tc_thread_pool.h" -#include "tup/Tars.h" -#include "tup/tup.h" +// #include "tup/tup.h" #include "util/tc_timeprovider.h" #include "servant/Application.h" + using namespace std; using namespace tars; -using namespace tup; - +// using namespace wup; Communicator* _comm; -//static string httpObj = "TestApp.HttpServer.httpObj@tcp -h 127.0.0.1 -p 8081"; -static string httpObj = "TestApp.HttpServer.httpObj@tcp -h 134.175.105.92 -p 8081"; +//static string httpObj = "TestApp.HttpServer.httpObj@tcp -h 127.0.0.1 -p 8081:tcp -h 127.0.0.1 -p 8082:tcp -h 127.0.0.1 -p 8083"; +static string httpObj = "TestApp.HttpServer.httpObj@tcp -h 127.0.0.1 -p 8081"; +//static string httpObj = "TestApp.HttpServer.httpObj@tcp -h 134.175.105.92 -p 8081"; struct Param { @@ -46,198 +31,272 @@ struct Param Param param; std::atomic callback_count(0); - void httpCall(int excut_num) { - int64_t _iTime = TC_TimeProvider::getInstance()->getNowMs(); + int64_t _iTime = TC_TimeProvider::getInstance()->getNowMs(); - // string sServer1("http://134.175.105.92:8081/"); - string sServer1("http://127.0.0.1:8081/"); + // string sServer1("http://134.175.105.92:8081/"); + string sServer1("http://127.0.0.1:8081/"); - TC_HttpRequest stHttpReq; - stHttpReq.setCacheControl("no-cache"); + TC_HttpRequest stHttpReq; + stHttpReq.setCacheControl("no-cache"); // stHttpReq.setGetRequest(sServer1); - TC_TCPClient client ; - // client.init("127.0.0.1", 8081, 3000); - client.init("127.0.0.1", 8082, 3000); - - int iRet = 0; - - for (int i = 0; igetNowMs() - _iTime <<"(ms)"<getNowMs() - _iTime <<"(ms)"< req = std::make_shared(); + req->setPostRequest("http://tars.com/hello", buff, true); +// req->setHeader("Connection", "keep-alive"); + + shared_ptr rsp; + + try + { + param.servantPrx->tars_hash(i)->http_call("hello", req, rsp); + assert(req->getContent() == rsp->getContent()); + } + catch(exception& e) + { + cout << "exception:" << e.what() << endl; + } + +// sleep(1); +// assert(req.use_count() == 1); +// assert(rsp.use_count() == 1); + ++callback_count; + } + + int64_t cost = TC_Common::now2us() - t; + cout << "syncCall total:" << cost << "us, avg:" << 1.*cost/c << "us" << endl; } struct TestHttpCallback : public HttpCallback { - TestHttpCallback(int64_t t, int i, int c) : start(t), cur(i), count(c) - { - - } - - virtual int onHttpResponse(const std::map& requestHeaders , - const std::map& responseHeaders , - const std::vector& rspBody) - { - callback_count++; - - if(cur == count-1) - { - int64_t cost = TC_Common::now2us() - start; - cout << "onHttpResponse count:" << count << ", " << cost << " us, avg:" << 1.*cost/count << "us" << endl; - } - - return 0; - } - virtual int onHttpResponseException(const std::map& requestHeaders, - int expCode) - { - cout << "onHttpResponseException expCode:" << expCode << endl; - - callback_count++; - - return 0; - } - - int64_t start; - int cur; - int count; + TestHttpCallback(const string &buff) : _buff(buff) + { + + } + + virtual int onHttpResponse(const shared_ptr &rsp) + { + callback_count++; + + assert(_buff == rsp->getContent()); + + return 0; + } + virtual int onHttpResponseException(int expCode) + { + cout << "onHttpResponseException expCode:" << expCode << endl; + + callback_count++; + + return 0; + } + + string _buff; }; -void syncRpc(int c) +void asyncRpc(int c) { int64_t t = TC_Common::now2us(); - std::map header; - - std::map rheader; - //发起远程调用 - for (int i = 0; i < c; ++i) - { - string rbody; - - try - { - param.servantPrx->http_call("GET", "/", header, "helloworld", rheader, rbody); - } - catch(exception& e) - { - cout << "exception:" << e.what() << endl; - } - ++callback_count; - } - - int64_t cost = TC_Common::now2us() - t; - cout << "syncCall total:" << cost << "us, avg:" << 1.*cost/c << "us" << endl; + //发起远程调用 + for (int i = 0; i < c; ++i) + { + shared_ptr req = std::make_shared(); + + string buff = string("helloworld-") + TC_Common::tostr(i); + req->setPostRequest("http://tars.com/hello", buff, true); +// req->setHeader("Connection", "keep-alive"); + + HttpCallbackPtr p = new TestHttpCallback(buff); + + try + { + param.servantPrx->http_call_async("hello", req, p); + } + catch(exception& e) + { + cout << "exception:" << e.what() << endl; + } + + if(i % 500 == 0) + { + TC_Common::msleep(100); + } + } + + int64_t cost = TC_Common::now2us() - t; + cout << "asyncRpc2 send:" << cost << "us, avg:" << 1.*cost/c << "us" << endl; +} + + +void asyncRpcCallback(int c) +{ + int64_t t = TC_Common::now2us(); + + _comm->setServantCustomCallback(param.servantPrx->tars_name(), [](ReqMessagePtr msg) { + msg->callback->dispatch(msg); + }); + + //发起远程调用 + for (int i = 0; i < c; ++i) + { + shared_ptr req = std::make_shared(); + + string buff = string("helloworld-") + TC_Common::tostr(i); + req->setPostRequest("http://tars.com/hello", buff, true); +// req->setHeader("Connection", "keep-alive"); + + HttpCallbackPtr p = new TestHttpCallback(buff); + + try + { + param.servantPrx->http_call_async("hello", req, p); + } + catch(exception& e) + { + cout << "exception:" << e.what() << endl; + } + + if(i % 500 == 0) + { + TC_Common::msleep(100); + } + } + + int64_t cost = TC_Common::now2us() - t; + cout << "asyncRpc2 send:" << cost << "us, avg:" << 1.*cost/c << "us" << endl; } int main(int argc, char *argv[]) { - try - { - if (argc < 4) - { - cout << "Usage:" << argv[0] << "--count=1000 --call=[basehttp|synchttp] --thread=1" << endl; + try + { + if (argc < 4) + { + cout << "Usage:" << argv[0] << "--count=1000 --call=[base|sync|async|callback] --thread=1" << endl; - return 0; - } + return 0; + } - TC_Option option; - option.decode(argc, argv); + TC_Option option; + option.decode(argc, argv); param.count = TC_Common::strto(option.getValue("count")); - if(param.count <= 0) param.count = 1000; - param.call = option.getValue("call"); - if(param.call.empty()) param.call = "sync"; - param.thread = TC_Common::strto(option.getValue("thread")); - if(param.thread <= 0) param.thread = 1; -/* + if(param.count <= 0) param.count = 1000; + param.call = option.getValue("call"); + if(param.call.empty()) param.call = "sync"; + param.thread = TC_Common::strto(option.getValue("thread")); + if(param.thread <= 0) param.thread = 1; + _comm = new Communicator(); -// TarsRollLogger::getInstance()->logger()->setLogLevel(6); + // LocalRollLogger::getInstance()->logger()->setLogLevel(6); _comm->setProperty("sendqueuelimit", "1000000"); _comm->setProperty("asyncqueuecap", "1000000"); - param.servantPrx = _comm->stringToProxy(httpObj); - - param.servantPrx->tars_connect_timeout(5000); - param.servantPrx->tars_async_timeout(60*1000); - - ProxyProtocol proto; - proto.requestFunc = ProxyProtocol::http1Request; - proto.responseFunc = ProxyProtocol::http1Response; - param.servantPrx->tars_set_protocol(proto); - */ - int64_t start = TC_Common::now2us(); - - std::function func; - - if (param.call == "basehttp") - { - func = httpCall; - } - else if (param.call == "synchttp") - { - func = syncRpc; - } - // else if(param.call == "asynchttp") - // { - // func = asyncRpc; - // } - else - { - cout << "no func, exits" << endl; - exit(0); - } - - vector vt; - for(int i = 0 ; i< param.thread; i++) - { - vt.push_back(new std::thread(func, param.count)); - } - - std::thread print([&]{while(callback_count != param.count * param.thread) { - cout << "Http:" << param.call << ": ----------finish count:" << callback_count << endl; - std::this_thread::sleep_for(std::chrono::seconds(1)); - };}); - - for(size_t i = 0 ; i< vt.size(); i++) - { - vt[i]->join(); - delete vt[i]; - } - - cout << "(pid:" << std::this_thread::get_id() << ")" - << "(count:" << param.count << ")" - << "(use ms:" << (TC_Common::now2us() - start)/1000 << ")" - << endl; - - while(callback_count != param.count * param.thread) { - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - print.join(); - cout << "----------finish count:" << callback_count << endl; - } - catch(exception &ex) - { - cout << ex.what() << endl; - } - cout << "main return." << endl; - - return 0; + param.servantPrx = _comm->stringToProxy(httpObj); + + int64_t start = TC_Common::now2us(); + + std::function func; + + if (param.call == "base") + { + func = httpCall; + } + else if (param.call == "sync") + { + func = syncRpc; + } + else if(param.call == "async") + { + func = asyncRpc; + } + else if(param.call == "callback") + { + func = asyncRpcCallback; + } + else + { + cout << "no func, exits" << endl; + exit(0); + } + + param.servantPrx->tars_connect_timeout(5000); + param.servantPrx->tars_async_timeout(60*1000); + + param.servantPrx->tars_set_protocol(ServantProxy::PROTOCOL_HTTP1, 3); + + vector vt; + for(int i = 0 ; i< param.thread; i++) + { + vt.push_back(new std::thread(func, param.count)); + } + + std::thread print([&]{while(callback_count != param.count * param.thread) { + cout << "Http:" << param.call << ": ----------finish count:" << callback_count << endl; + std::this_thread::sleep_for(std::chrono::seconds(1)); + };}); + + for(size_t i = 0 ; i< vt.size(); i++) + { + vt[i]->join(); + delete vt[i]; + } + + cout << "(pid:" << std::this_thread::get_id() << ")" + << "(count:" << param.count << ")" + << "(use ms:" << (TC_Common::now2us() - start)/1000 << ")" + << endl; + + while(callback_count != param.count * param.thread) { + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + print.join(); + cout << "----------finish count:" << callback_count << endl; + + delete _comm; + _comm = NULL; + } + catch(exception &ex) + { + cout << ex.what() << endl; + } + cout << "main return." << endl; + + return 0; } \ No newline at end of file diff --git a/examples/HttpDemo/HttpServer/HttpImp.cpp b/examples/HttpDemo/HttpServer/HttpImp.cpp index 34745e33c4743eb2a0dade9a5df8271f5e6d8932..243d7889834c0794662e44b65579e66cfc070672 100644 --- a/examples/HttpDemo/HttpServer/HttpImp.cpp +++ b/examples/HttpDemo/HttpServer/HttpImp.cpp @@ -35,17 +35,17 @@ void HttpImp::destroy() int HttpImp::doRequest(TarsCurrentPtr current, vector &buffer) { - TC_HttpRequest request; + TC_HttpRequest request; + vector v = current->getRequestBuffer(); - string sBuf; - sBuf.assign(v.data(),v.size()); - request.decode(sBuf); - // cout << request.getContent() << endl; + request.decode(current->getRequestBuffer()); + TC_HttpResponse rsp; - string s="hello"; + string s=request.getContent(); rsp.setResponse(s.c_str(),s.size()); + rsp.setHeader("Connection", request.getHeader("Connection")); rsp.encode(buffer); - + return 0; } diff --git a/examples/QuickStartDemo/HelloServer/Client/main.cpp b/examples/QuickStartDemo/HelloServer/Client/main.cpp index 386f8333ed96f8c1c81444ec3c075b1b78f730a0..291bea68ca94787b7dd0639d9ce98e09eeff869c 100644 --- a/examples/QuickStartDemo/HelloServer/Client/main.cpp +++ b/examples/QuickStartDemo/HelloServer/Client/main.cpp @@ -300,7 +300,7 @@ int main(int argc, char *argv[]) _comm->setProperty("netthread", TC_Common::tostr(param.netthread)); -// TarsRollLogger::getInstance()->logger()->setLogLevel(6); +// LocalRollLogger::getInstance()->logger()->setLogLevel(6); param.pPrx = _comm->stringToProxy(helloObj); diff --git a/examples/QuickStartDemo/HelloServer/Server/HelloImp.cpp b/examples/QuickStartDemo/HelloServer/Server/HelloImp.cpp index e0d5a2c5e0d9dc23d882d9330439ab36e812d6cc..47c63509f2f99707ac7c0cc1603c9f8a8389dd7c 100644 --- a/examples/QuickStartDemo/HelloServer/Server/HelloImp.cpp +++ b/examples/QuickStartDemo/HelloServer/Server/HelloImp.cpp @@ -35,7 +35,7 @@ void HelloImp::destroy() int HelloImp::testHello(const std::string &sReq, std::string &sRsp, tars::TarsCurrentPtr current) { - TLOGDEBUG("HelloImp::testHellosReq:"< #server crt - ca = ./examples/SSLDemo/certs/server1.crt + ca = ../examples/SSLDemo/certs/server1.crt #can be empty - # cert = ./examples/SSLDemo/certs/client1.crt + # cert = ../examples/SSLDemo/certs/client1.crt #can be empty - # key = ./examples/SSLDemo/certs/client1.key + # key = ../examples/SSLDemo/certs/client1.key #server crt - ca = ./examples/SSLDemo/certs/server1.crt + ca = ../examples/SSLDemo/certs/server1.crt #can be empty - cert = ./examples/SSLDemo/certs/client1.crt + cert = ../examples/SSLDemo/certs/client1.crt #can be empty - key = ./examples/SSLDemo/certs/client1.key + key = ../examples/SSLDemo/certs/client1.key @@ -53,11 +53,11 @@ #auth secret key secretkey = 123456 #server crt - ca = ./examples/SSLDemo/certs/server1.crt + ca = ../examples/SSLDemo/certs/server1.crt #can be empty - cert = ./examples/SSLDemo/certs/client1.crt + cert = ../examples/SSLDemo/certs/client1.crt #can be empty - key = ./examples/SSLDemo/certs/client1.key + key = ../examples/SSLDemo/certs/client1.key diff --git a/examples/SSLDemo/Client/main.cpp b/examples/SSLDemo/Client/main.cpp index 3db68db9347921cc8d88efb56b979af60179b9c6..8dd85811fb6f234d185ea7a2cac4068ea2b76961 100644 --- a/examples/SSLDemo/Client/main.cpp +++ b/examples/SSLDemo/Client/main.cpp @@ -162,7 +162,7 @@ int main(int argc, char *argv[]) conf.parseFile(option.getValue("config")); _comm->setProperty(conf); -// TarsRollLogger::getInstance()->logger()->setLogLevel(6); +// LocalRollLogger::getInstance()->logger()->setLogLevel(6); _comm->setProperty("sendqueuelimit", "1000000"); _comm->setProperty("asyncqueuecap", "1000000"); diff --git a/examples/SSLDemo/Server/config.conf b/examples/SSLDemo/Server/config.conf index 4c56ef082dd9b00080597a6ef51f350e790d7a56..6570aeb5b39471cc8dc1f500b2d7ab626dd9feba 100755 --- a/examples/SSLDemo/Server/config.conf +++ b/examples/SSLDemo/Server/config.conf @@ -52,9 +52,9 @@ # log = tars.tarslog.LogObj #client crt, it can be empty when verifyclient is 0 - ca = ./examples/SSLDemo/certs/client.crt - cert = ./examples/SSLDemo/certs/server.crt - key = ./examples/SSLDemo/certs/server.key + ca = ../examples/SSLDemo/certs/client.crt + cert = ../examples/SSLDemo/certs/server.crt + key = ../examples/SSLDemo/certs/server.key #default is 0 verifyclient = 1 @@ -90,9 +90,9 @@ queuecap = 1000000 #tars protocol protocol = tars - # ca = ./examples/SSLDemo/certs/client1.crt - cert = ./examples/SSLDemo/certs/server1.crt - key = ./examples/SSLDemo/certs/server1.key + # ca = ../examples/SSLDemo/certs/client1.crt + cert = ../examples/SSLDemo/certs/server1.crt + key = ../examples/SSLDemo/certs/server1.key #default is 0 verifyclient = 0 @@ -112,9 +112,9 @@ queuecap = 1000000 #tars protocol protocol = tars - ca = ./examples/SSLDemo/certs/client1.crt - cert = ./examples/SSLDemo/certs/server1.crt - key = ./examples/SSLDemo/certs/server1.key + ca = ../examples/SSLDemo/certs/client1.crt + cert = ../examples/SSLDemo/certs/server1.crt + key = ../examples/SSLDemo/certs/server1.key #default is 0 verifyclient = 1 @@ -138,9 +138,9 @@ accesskey = tars-test-user #auth secret key secretkey = 123456 - ca = ./examples/SSLDemo/certs/client1.crt - cert = ./examples/SSLDemo/certs/server1.crt - key = ./examples/SSLDemo/certs/server1.key + ca = ../examples/SSLDemo/certs/client1.crt + cert = ../examples/SSLDemo/certs/server1.crt + key = ../examples/SSLDemo/certs/server1.key #default is 0 verifyclient = 1 diff --git a/examples/UdpDemo/CMakeLists.txt b/examples/UdpDemo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..6345c283747758c9a6a622b360421626a1c1cbab --- /dev/null +++ b/examples/UdpDemo/CMakeLists.txt @@ -0,0 +1,5 @@ + +include_directories(Server) +add_subdirectory(Server) +add_subdirectory(Client) + diff --git a/examples/UdpDemo/Client/CMakeLists.txt b/examples/UdpDemo/Client/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..53d3c5c22e07a8f41f20fe4c01d7c2c9c13d62ef --- /dev/null +++ b/examples/UdpDemo/Client/CMakeLists.txt @@ -0,0 +1 @@ +build_tars_server(UdpClient UdpServer) diff --git a/examples/UdpDemo/Client/config.conf b/examples/UdpDemo/Client/config.conf new file mode 100755 index 0000000000000000000000000000000000000000..c2a9796140c3f73b8f70ff08b923a8de002c9364 --- /dev/null +++ b/examples/UdpDemo/Client/config.conf @@ -0,0 +1,28 @@ + + + + + #tarsregistry locator + locator = tars.tarsregistry.QueryObj@tcp -h 127.0.0.1 -p 17890 + #max invoke timeout + sync-invoke-timeout = 5000 + #refresh endpoint interval + refresh-endpoint-interval = 10000 + #stat obj + stat = tars.tarsstat.StatObj + #max send queue length limit + sendqueuelimit = 100000 + #async queue length limit + asyncqueuecap = 100000 + #async callback thread num + asyncthread = 3 + #net thread + netthread = 1 + #merge net and sync thread + mergenetasync = 0 + #module name + modulename = TestApp.UdpClient + + + + diff --git a/examples/UdpDemo/Client/main.cpp b/examples/UdpDemo/Client/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d91b236e2bc52b7177c4fbe7c232c81773de4f7d --- /dev/null +++ b/examples/UdpDemo/Client/main.cpp @@ -0,0 +1,243 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT 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 "servant/Communicator.h" +#include "Hello.h" +#include "util/tc_option.h" + +using namespace std; +using namespace tars; +using namespace TestApp; + +Communicator* _comm; + +static string helloObj = "TestApp.UdpServer.UdpObj@udp -h 127.0.0.1 -p 9016 -e 1"; +static string ipv6Obj = "TestApp.UdpServer.Ipv6Obj@udp -h ::1 -p 25460"; + +struct Param +{ + int count; + string call; + int thread; + int buffersize; + int netthread; + + HelloPrx pPrx; +}; + +Param param; +std::atomic request_count(0); +std::atomic callback_count(0); + +struct HelloCallback : public HelloPrxCallback +{ + HelloCallback(int64_t t, int i, int c) : start(t), cur(i), count(c) + { + + } + + //call back + virtual void callback_testHello(int ret, const string &r) + { + assert(ret == 0); + callback_count++; + + if(cur == count-1) + { + int64_t cost = TC_Common::now2us() - start; + cout << "callback_testHello count:" << count << ", " << cost << " us, avg:" << 1.*cost/count << "us" << endl; + } + } + + virtual void callback_testHello_exception(tars::Int32 ret) + { + cout << "callback exception:" << ret << endl; + } + + int64_t start; + int cur; + int count; +}; + + +void syncCall(int c) +{ + string buffer(param.buffersize, 'a'); + + int64_t t = TC_Common::now2us(); + //发起远程调用 + for (int i = 0; i < c; ++i) + { + string r; + + try + { + param.pPrx->testHello(buffer, r); + } + catch(exception& e) + { + cout << "exception:" << e.what() << endl; + } + ++callback_count; + } + + int64_t cost = TC_Common::now2us() - t; + cout << "syncCall total:" << cost << "us, avg:" << 1.*cost/c << "us" << endl; +} + +void asyncCall(int c) +{ + int64_t t = TC_Common::now2us(); + + string buffer(param.buffersize, 'a'); + + //发起远程调用 + for (int i = 0; i < c;) + { + if(request_count - callback_count < 100) { + i++; + request_count++; + HelloPrxCallbackPtr p = new HelloCallback(t, i, c); + try { + param.pPrx->async_testHello(p, buffer); + } + catch (exception & e) { + cout << "exception:" << e.what() << endl; + } + } + else + { + TC_Common::msleep(10); + } + } + + int64_t cost = TC_Common::now2us() - t; + cout << "asyncCall send:" << cost << "us, avg:" << 1.*cost/c << "us" << endl; +} + +int main(int argc, char *argv[]) +{ + try + { + if (argc < 6) + { + cout << "Usage:" << argv[0] << "--config=conf --count=1000 --call=[sync|async|syncv6|asyncv6] --thread=1 --buffersize=1000 --netthread=1" << endl; + + return 0; + } + + TC_Option option; + option.decode(argc, argv); + + param.count = TC_Common::strto(option.getValue("count")); + if(param.count <= 0) param.count = 1000; + param.buffersize = TC_Common::strto(option.getValue("buffersize")); + if(param.buffersize <= 0) param.buffersize = 1000; + param.call = option.getValue("call"); + if(param.call.empty()) param.call = "sync"; + param.thread = TC_Common::strto(option.getValue("thread")); + if(param.thread <= 0) param.thread = 1; + param.netthread = TC_Common::strto(option.getValue("netthread")); + if(param.netthread <= 0) param.netthread = 1; + + _comm = new Communicator(); + + TC_Config conf; + conf.parseFile(option.getValue("config")); + _comm->setProperty(conf); + +// TafRollLogger::getInstance()->logger()->setLogLevel(6); + + _comm->setProperty("sendqueuelimit", "1000000"); + _comm->setProperty("asyncqueuecap", "1000000"); + + _comm->setProperty("netthread", TC_Common::tostr(param.netthread)); + + + int64_t start = TC_Common::now2us(); + + std::function func; + + if (param.call == "sync") + { + func = syncCall; + param.pPrx = _comm->stringToProxy(helloObj); + + } + else if (param.call == "async") + { + func = asyncCall; + param.pPrx = _comm->stringToProxy(helloObj); + + } + else if (param.call == "syncv6") + { + func = syncCall; + param.pPrx = _comm->stringToProxy(ipv6Obj); + + } + else if (param.call == "asyncv6") + { + func = asyncCall; + param.pPrx = _comm->stringToProxy(ipv6Obj); + } + else + { + cout << "no func, exits" << endl; + exit(0); + } + + param.pPrx->tars_connect_timeout(5000); + param.pPrx->tars_async_timeout(60*1000); + param.pPrx->tars_ping(); + + vector vt; + for(int i = 0 ; i< param.thread; i++) + { + vt.push_back(new std::thread(func, param.count)); + } + + std::thread print([&]{while(callback_count != param.count * param.thread) { + cout << "Auth:" << param.call << " : ----------finish count:" << callback_count << endl; + std::this_thread::sleep_for(std::chrono::seconds(1)); + };}); + + for(size_t i = 0 ; i< vt.size(); i++) + { + vt[i]->join(); + delete vt[i]; + } + + cout << "(pid:" << std::this_thread::get_id() << ")" + << "(count:" << param.count << ")" + << "(use ms:" << (TC_Common::now2us() - start)/1000 << ")" + << endl; + + while(callback_count != param.count * param.thread) { + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + print.join(); + cout << "Auth:" << param.call << " ----------finish count:" << callback_count << endl; + } + catch(exception &ex) + { + cout << ex.what() << endl; + } + cout << "main return." << endl; + + return 0; +} diff --git a/examples/UdpDemo/Server/CMakeLists.txt b/examples/UdpDemo/Server/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b7a66735fcb30640e56ad7b978f40d794c8d56ce --- /dev/null +++ b/examples/UdpDemo/Server/CMakeLists.txt @@ -0,0 +1,2 @@ +build_tars_server("UdpServer" "") + diff --git a/examples/UdpDemo/Server/Hello.tars b/examples/UdpDemo/Server/Hello.tars new file mode 100644 index 0000000000000000000000000000000000000000..174c4f32270b9f8664775ab98f0b03db09b2c498 --- /dev/null +++ b/examples/UdpDemo/Server/Hello.tars @@ -0,0 +1,26 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +module TestApp +{ + +interface Hello +{ + int test(); + int testHello(string sReq, out string sRsp); +}; + +}; diff --git a/examples/UdpDemo/Server/HelloImp.cpp b/examples/UdpDemo/Server/HelloImp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b8cf947d72ee58db15b0c3aaff5901d07029736e --- /dev/null +++ b/examples/UdpDemo/Server/HelloImp.cpp @@ -0,0 +1,43 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT 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 "HelloImp.h" +#include "servant/Application.h" + +using namespace std; + +////////////////////////////////////////////////////// +void HelloImp::initialize() +{ + //initialize servant here: + //... +} + +////////////////////////////////////////////////////// +void HelloImp::destroy() +{ + //destroy servant here: + //... +} + +int HelloImp::testHello(const std::string &sReq, std::string &sRsp, tars::TarsCurrentPtr current) +{ +// TLOGDEBUG("HelloImp::testHellosReq:"<(ServerConfig::Application + "." + ServerConfig::ServerName + ".UdpObj"); + addServant(ServerConfig::Application + "." + ServerConfig::ServerName + ".Ipv6Obj"); +} +///////////////////////////////////////////////////////////////// +void +HelloServer::destroyApp() +{ + //destroy application here: + //... +} +///////////////////////////////////////////////////////////////// +int +main(int argc, char* argv[]) +{ + try + { + g_app.main(argc, argv); + g_app.waitForShutdown(); + } + catch (std::exception& e) + { + cerr << "std::exception:" << e.what() << std::endl; + } + catch (...) + { + cerr << "unknown exception." << std::endl; + } + return -1; +} +///////////////////////////////////////////////////////////////// diff --git a/examples/UdpDemo/Server/HelloServer.h b/examples/UdpDemo/Server/HelloServer.h new file mode 100644 index 0000000000000000000000000000000000000000..0fbc36bfed6dfa18346ab25b4e2d2b501e9a993b --- /dev/null +++ b/examples/UdpDemo/Server/HelloServer.h @@ -0,0 +1,50 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT 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 _HelloServer_H_ +#define _HelloServer_H_ + +#include +#include "servant/Application.h" + +using namespace tars; + +/** + * + **/ +class HelloServer : public Application +{ +public: + /** + * + **/ + virtual ~HelloServer() {}; + + /** + * + **/ + virtual void initialize(); + + /** + * + **/ + virtual void destroyApp(); +}; + +extern HelloServer g_app; + +//////////////////////////////////////////// +#endif diff --git a/examples/UdpDemo/Server/config.conf b/examples/UdpDemo/Server/config.conf new file mode 100755 index 0000000000000000000000000000000000000000..8aa4f0d1741bd443cd17819095c171effd7c9b74 --- /dev/null +++ b/examples/UdpDemo/Server/config.conf @@ -0,0 +1,87 @@ + + + + + #tarsregistry locator + locator = tars.tarsregistry.QueryObj@tcp -h 127.0.0.1 -p 17890 + #max invoke timeout + sync-invoke-timeout = 5000 + #refresh endpoint interval + refresh-endpoint-interval = 10000 + #stat obj + stat = tars.tarsstat.StatObj + #max send queue length limit + sendqueuelimit = 100000 + #async queue length limit + asyncqueuecap = 100000 + #async callback thread num + asyncthread = 3 + #net thread + netthread = 1 + #merge net and sync thread + mergenetasync = 0 + #module name + modulename = TestApp.UdpServer + + + + + #not cout + closecout = 0 + #app name + app = TestApp + #server name + server = UdpServer + #path + basepath = ./ + datapath = ./ + #log path + logpath = ./ + #merge net and imp thread + mergenetimp = 0 + #local ip, for tarsnode +# local = tcp -h 127.0.0.1 -p 15001 -t 10000 + + #tarsnode +# node = ServerObj@tcp -h 127.0.0.1 -p 2345 -t 10000 + #config obj +# config = tars.tarsconfig.ConfigObj + #notify obj +# notify = tars.tarsconfig.NotifyObj + #log obj +# log = tars.tarslog.LogObj + + + #ip:port:timeout + endpoint = udp -h 127.0.0.1 -p 9016 -t 10000 -e 1 + #allow ip + allow = + #max connection num + maxconns = 4096 + #imp thread num + threads = 5 + #servant + servant = TestApp.UdpServer.UdpObj + #queue capacity + queuecap = 1000000 + #tars protocol + protocol = tars + + + + #ip:port:timeout + endpoint = udp -h ::1 -p 25460 -t 10000 + #允许的IP地址 + allow = + #最大连接数 + maxconns = 4096 + #当前线程个数 + threads = 5 + #处理对象 + servant = TestApp.UdpServer.Ipv6Obj + #队列最大包个数 + queuecap = 1000000 + + + + diff --git a/examples/UtilDemo/demo-util/CMakeLists.txt b/examples/UtilDemo/demo-util/CMakeLists.txt index 1f516c01aef28360221581519e2d314e3385e909..053d52c0bafa53bd2657489a8865581bdf248fc6 100644 --- a/examples/UtilDemo/demo-util/CMakeLists.txt +++ b/examples/UtilDemo/demo-util/CMakeLists.txt @@ -1,17 +1,18 @@ include_directories(${util_SOURCE_DIR}/include) - -link_libraries(tarsutil) +include_directories(${CMAKE_BINARY_DIR}/src/gtest/include) +link_directories(${CMAKE_BINARY_DIR}/src/gtest/lib) +link_directories(${CMAKE_BINARY_DIR}/src/gtest/lib64) FILE(GLOB_RECURSE SRC_LIST "*.cpp") if (TARS_SSL) if (WIN32) - link_libraries(tarsutil ${LIB_SSL} ${LIB_CRYPTO} Crypt32) + link_libraries(tarsutil gtest ${LIB_SSL} ${LIB_CRYPTO} Crypt32) else () - link_libraries(tarsutil ${LIB_SSL} ${LIB_CRYPTO}) + link_libraries(tarsutil gtest ${LIB_SSL} ${LIB_CRYPTO}) endif () else () - link_libraries(tarsutil) + link_libraries(tarsutil gtest) endif () add_executable(demo-util ${SRC_LIST}) diff --git a/examples/UtilDemo/demo-util/main.cpp b/examples/UtilDemo/demo-util/main.cpp index a481dd6246140456bd2028c0e640fba4003be221..716dcff8bfa544c213c2c9c8cf6bf61fa26aab9f 100644 --- a/examples/UtilDemo/demo-util/main.cpp +++ b/examples/UtilDemo/demo-util/main.cpp @@ -1,31 +1,12 @@ #include #include #include -#include "test_base.h" +#include "gtest/gtest.h" using namespace std; int main(int argc, char** argv) { - try - { - vector tests; - tests.push_back(new Test_TC_File()); - - for(auto t : tests) - { - t->test(); - } - - for(auto t: tests) - { - delete t; - } - tests.clear(); - - } - catch (exception &ex) - { - cerr << "main ex:" << ex.what() << endl; - } + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); } \ No newline at end of file diff --git a/examples/UtilDemo/demo-util/test_base.h b/examples/UtilDemo/demo-util/test_base.h deleted file mode 100644 index c5bbe0dacb513ac65c4062239723f79d9585833c..0000000000000000000000000000000000000000 --- a/examples/UtilDemo/demo-util/test_base.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Created by jarod on 2020/2/20. -// - -#ifndef TARS_CPP_TEST_BASE_H -#define TARS_CPP_TEST_BASE_H - -class Test_Base -{ -public: - virtual void test() = 0; - virtual ~Test_Base(){} -}; - -class Test_TC_File : public Test_Base -{ -public: - virtual void test(); -}; - -#endif //TARS_CPP_TEST_BASE_H diff --git a/examples/UtilDemo/demo-util/test_tc_file.cpp b/examples/UtilDemo/demo-util/test_tc_file.cpp index 46378387e345c7fc9e614e55ea29e812bccab5c9..b484a5da88c29c4942ea254ce24193b00ab1831e 100644 --- a/examples/UtilDemo/demo-util/test_tc_file.cpp +++ b/examples/UtilDemo/demo-util/test_tc_file.cpp @@ -1,13 +1,35 @@ -// +// // Created by jarod on 2020/2/20. // #include "util/tc_file.h" -#include "test_base.h" +#include "gtest/gtest.h" using namespace tars; -void Test_TC_File::test() +class FileTest : public testing::Test +{ +public: + //添加日志 + static void SetUpTestCase() + { + cout<<"SetUpTestCase"< buff; + + req.encode(buff); + } + + cout << "testEncodeVector::cost: " << TC_Common::now2us() - t << "us, " << 1.*(TC_Common::now2us() - t)/count << "us" << endl; +} + +TEST_F(HttpTest, testEncodeBuffString) //此时使用的是TEST_F宏 +{ + string s = string("GET /a/b?name=value&ccc=ddd HTTP/1.1\\r\n") + +string("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n") + +string("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n") + +string("Accept-Encoding: gzip\r\n") + +string("Accept-Language: zh-cn,zh;q=0.5\r\n") + +string("Connection: close\r\n") + +string("Host: www.qq.com\r\n") + +string("Q-GUID: 08f0373a192a45778cc8567d1c641475\r\n") + +string("Q-UA: SQB12_GA/120450&SMTT_3/020100&SYM3&201514&E71&V2\r\n") + +string("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n"); + + int64_t t = TC_Common::now2us(); + + TC_HttpRequest req; + req.decode(s); + + TC_NetWorkBuffer buff(NULL); + + int count = 100000; + int i = 0; + while(++i vbuff; + while(i sbuff; + sbuff.push_back("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n"); + sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n"); + sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n"); + sbuff.push_back("Accept-Encoding: gzip\r\n"); + sbuff.push_back("Content-Length: " + TC_Common::tostr(body.size()) + "\r\n"); + sbuff.push_back("Connection: close\r\n"); + sbuff.push_back("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n"); + + string header; + for(auto s : sbuff) + { + header += s; + } + + string s = header + body; + + TC_HttpRequest request; + ASSERT_TRUE(request.checkRequest(s.c_str(), s.size())); + + TC_NetWorkBuffer buff(NULL); + buff.addBuffer(s.c_str(), s.size()); + + ASSERT_TRUE(buff.checkHttp() == TC_NetWorkBuffer::PACKET_FULL); +} + +TEST_F(HttpTest, testHttpFinishNoLength) //此时使用的是TEST_F宏 +{ + vector sbuff; + sbuff.push_back("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n"); + sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n"); + sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n"); + sbuff.push_back("Accept-Encoding: gzip\r\n"); + sbuff.push_back("Connection: close\r\n"); + sbuff.push_back("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n"); + + string header; + for(auto s : sbuff) + { + header += s; + } + + string s = header; + + TC_HttpRequest request; + ASSERT_TRUE(request.checkRequest(s.c_str(), s.size())); + + TC_NetWorkBuffer buff(NULL); + buff.addBuffer(s.c_str(), s.size()); + + ASSERT_TRUE(buff.checkHttp() == TC_NetWorkBuffer::PACKET_FULL); +} + +TEST_F(HttpTest, testHttpNoFinish) //此时使用的是TEST_F宏 +{ + string body = "abdefghigk"; + + vector sbuff; + sbuff.push_back("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n"); + sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n"); + sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n"); + sbuff.push_back("Accept-Encoding: gzip\r\n"); + sbuff.push_back("Content-Length: " + TC_Common::tostr(body.size() + 1) + "\r\n"); + sbuff.push_back("Connection: close\r\n"); + sbuff.push_back("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n"); + + string header; + for(auto s : sbuff) + { + header += s; + } + + string s = header + body; + + TC_HttpRequest request; + ASSERT_TRUE(!request.checkRequest(s.c_str(), s.size())); + + TC_NetWorkBuffer buff(NULL); + buff.addBuffer(s.c_str(), s.size()); + + ASSERT_TRUE(buff.checkHttp() == TC_NetWorkBuffer::PACKET_LESS); +} + +TEST_F(HttpTest, testHttpRequestChunked) //此时使用的是TEST_F宏 +{ + vector body; + body.push_back("abasdfadefghiadfagk1"); + body.push_back("abdasdfadfaefghigk2"); + body.push_back("abdsaefghigk3"); + body.push_back("abdeasdfafasfasfasfasdfasffghigk4"); + + vector sbuff; + sbuff.push_back("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n"); + sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n"); + sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n"); + sbuff.push_back("Accept-Encoding: gzip\r\n"); + sbuff.push_back("Transfer-Encoding: chunked\r\n"); + sbuff.push_back("Connection: close\r\n"); + sbuff.push_back("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n"); + + stringstream data; + for(auto s : sbuff) + { + data << s; + } + + string sbody; + for(auto s : body) + { + sbody += s; + data << hex << s.size() << "\r\n" << s << "\r\n"; + } + data << 0 << "\r\n\r\n"; + + string s = data.str(); + + TC_HttpRequest request; + ASSERT_TRUE(request.checkRequest(s.c_str(), s.size())); + ASSERT_TRUE(request.decode(s)); + + ASSERT_TRUE(request.getContent() == sbody); + + TC_NetWorkBuffer buff(NULL); + buff.addBuffer(s.c_str(), s.size()); + + request.reset(); + ASSERT_TRUE(request.checkRequest(buff)); + +} + +TEST_F(HttpTest, testHttpRequestChunkedNoFinish) //此时使用的是TEST_F宏 +{ + vector body; + body.push_back("abasdfadefghiadfagk1"); + body.push_back("abdasdfadfaefghigk2"); + body.push_back("abdsaefghigk3"); + body.push_back("abdeasdfafasfasfasfasdfasffghigk4"); + + vector sbuff; + sbuff.push_back("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n"); + sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n"); + sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n"); + sbuff.push_back("Accept-Encoding: gzip\r\n"); + sbuff.push_back("Transfer-Encoding: chunked\r\n"); + sbuff.push_back("Connection: close\r\n"); + sbuff.push_back("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n"); + + stringstream data; + for(auto s : sbuff) + { + data << s; + } + + data << hex << body[0].size() << "\r\n" << body[0] << "\r\n"; + data << hex << body[1].size() << "\r\n" << body[1] << "\r\n"; + data << hex << body[2].size() ; + + string s = data.str(); + + TC_HttpRequest request; + ASSERT_TRUE(!request.checkRequest(s.c_str(), s.size())); + + TC_NetWorkBuffer buff(NULL); + buff.addBuffer(s.c_str(), s.size()); + + ASSERT_TRUE(!request.checkRequest(buff)); + +} + +TEST_F(HttpTest, testHttpResponse) //此时使用的是TEST_F宏 +{ + string body = "abcdef"; + + vector sbuff; + sbuff.push_back("HTTP/1.1 200 OK\r\n"); + sbuff.push_back("Content-Length: " + TC_Common::tostr(body.size()) + "\r\n"); + sbuff.push_back("\r\n"); + + string header; + for(auto s : sbuff) + { + header += s; + } + + string s = header + body; + + { + TC_HttpResponse response; + ASSERT_TRUE(response.decode(s)); + ASSERT_TRUE(response.getContent() == body); + + } + + { + TC_HttpResponse response; + TC_NetWorkBuffer buff(NULL); + buff.addBuffer(s.c_str(), s.size()); + + ASSERT_TRUE(response.incrementDecode(buff)); + ASSERT_TRUE(response.getContent() == body); + + } +} + +TEST_F(HttpTest, testHttpResponseNoFinish) //此时使用的是TEST_F宏 +{ + string body = "abcdef"; + + vector sbuff; + sbuff.push_back("HTTP/1.1 200 OK\r\n"); + sbuff.push_back("Content-Length: " + TC_Common::tostr(body.size() + 1) + "\r\n"); + sbuff.push_back("\r\n"); + + string header; + for(auto s : sbuff) + { + header += s; + } + + string s = header + body; + + { + TC_HttpResponse response; + ASSERT_TRUE(!response.decode(s)); + } + + { + TC_HttpResponse response; + TC_NetWorkBuffer buff(NULL); + buff.addBuffer(s.c_str(), s.size()); + + ASSERT_TRUE(!response.incrementDecode(buff)); + } +} + +TEST_F(HttpTest, testHttpResponseNoLength) //此时使用的是TEST_F宏 +{ + vector sbuff; + sbuff.push_back("HTTP/1.1 200 OK\r\n"); + sbuff.push_back("Connection: close\r\n"); + sbuff.push_back("\r\n"); + + string header; + for(auto s : sbuff) + { + header += s; + } + + string s = header; + + { + TC_HttpResponse response; + ASSERT_TRUE(response.decode(s)); + } + + { + TC_HttpResponse response; + TC_NetWorkBuffer buff(NULL); + buff.addBuffer(s.c_str(), s.size()); + + ASSERT_TRUE(response.incrementDecode(buff)); + } +} + +TEST_F(HttpTest, testHttpResponseIncrementFinish) //此时使用的是TEST_F宏 +{ + string body = "abcdeasdfadfsff"; + + vector sbuff; + sbuff.push_back("HTTP/1.1 200 OK\r\n"); + sbuff.push_back("Content-Length: " + TC_Common::tostr(body.size()) + "\r\n"); + sbuff.push_back("\r\n"); + + string header; + for(auto s : sbuff) + { + header += s; + } + + string s = header; + + { + TC_HttpResponse response; + ASSERT_TRUE(!response.decode(s)); + } + + { + TC_HttpResponse response; + TC_NetWorkBuffer buff(NULL); + buff.addBuffer(s.c_str(), s.size()); + + ASSERT_TRUE(!response.incrementDecode(buff)); + } + + s = header + body; + { + TC_HttpResponse response; + ASSERT_TRUE(response.decode(s)); + } + + { + TC_HttpResponse response; + TC_NetWorkBuffer buff(NULL); + buff.addBuffer(s.c_str(), s.size()); + + ASSERT_TRUE(response.incrementDecode(buff)); + } + +} + +TEST_F(HttpTest, testHttpResponseChunked) //此时使用的是TEST_F宏 +{ + vector body; + body.push_back("abdefghiasdfasdfsadfsadfsagk1"); + body.push_back("abdefghasdfaaigk2"); + body.push_back("abdefghigadsfadsfk3"); + body.push_back("abdefgsfagasasdfasfdfdfsdfsfsdfdsffsdfsdfhigk4"); + + vector sbuff; + sbuff.push_back("HTTP/1.1 200 OK\r\n"); + sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n"); + sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n"); + sbuff.push_back("Transfer-Encoding: chunked\r\n"); + sbuff.push_back("Connection: close\r\n\r\n"); + + stringstream data; + for(auto s : sbuff) + { + data << s; + } + + string sbody; + for(auto s : body) + { + sbody += s; + + data << hex << s.size() << "\r\n" << s << "\r\n"; + } + data << 0 << "\r\n\r\n"; + + string s = data.str(); + + { + TC_HttpResponse response; + ASSERT_TRUE(response.decode(s)); + + ASSERT_TRUE(response.getContent() == sbody); + } + + { + TC_HttpResponse response; + TC_NetWorkBuffer buff(NULL); + buff.addBuffer(s.c_str(), s.size()); + + ASSERT_TRUE(response.incrementDecode(buff)); + + ASSERT_TRUE(response.getContent() == sbody); + } +} + +TEST_F(HttpTest, testHttpResponseChunkedNoFinish) //此时使用的是TEST_F宏 +{ + vector body; + body.push_back("abdefasdfasfasghigk1"); + body.push_back("asdfaabdeafghigk2"); + body.push_back("abasdfasdfasdfasdfasdfasdfasfasdefghigk3"); + body.push_back("abdefgfasdfasdfasdfasdfadfigk4"); + + vector sbuff; + sbuff.push_back("HTTP/1.1 200 OK\r\n"); + sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n"); + sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n"); + sbuff.push_back("Transfer-Encoding: chunked\r\n"); + sbuff.push_back("Connection: close\r\n\r\n"); + + stringstream data; + for(auto s : sbuff) + { + data << s; + } + + data << hex << body[0].size() << "\r\n" << body[0] << "\r\n"; + data << hex << body[1].size() << "\r\n" << body[1] << "\r\n"; + data << hex << body[2].size() << "\r\n" << "abc"; + + string s = data.str(); + + { + TC_HttpResponse response; + ASSERT_TRUE(!response.decode(s)); + + } + + { + TC_HttpResponse response; + + TC_NetWorkBuffer buff(NULL); + buff.addBuffer(s.c_str(), s.size()); + + ASSERT_TRUE(!response.incrementDecode(buff)); + } +} + +TEST_F(HttpTest, testWeb) //此时使用的是TEST_F宏 +{ + string url = "www.qq.com"; + TC_HttpRequest stHttpReq; +// stHttpReq.setCacheControl("no-cache"); +// stHttpReq.setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36"); + stHttpReq.setUserAgent("E71/SymbianOS/9.1 Series60/3.0"); + stHttpReq.setHeader("Connection", "Close"); + stHttpReq.setAcceptEncoding("gzip, deflate, br"); + stHttpReq.setGetRequest(url); + + string sSendBuffer = stHttpReq.encode(); + + TC_HttpResponse stHttpRsp; + int iRet = stHttpReq.doRequest(stHttpRsp, 5000); + if(iRet != 0) + { + cout << iRet << endl; + } + + string file = stHttpReq.getURL().getDomain() + ".html"; + + auto headers = stHttpRsp.getHeaders(); + + cout << "request:" << url << endl; + cout << TC_Common::tostr(headers.begin(), headers.end(), "\r\n") << endl; + TC_File::save2file(file, stHttpRsp.getContent()); + +// ASSERT_TRUE(stHttpRsp.getContentLength() == TC_File::getFileSize(file)); +} + +void testCookie(const string &sRspURL, const string &sReqURL, const vector &vsCookie) +{ + cout << sRspURL << "=>" << sReqURL << "-----------------------------------" << endl; + + TC_HttpCookie cookie; + + cookie.addCookie(sRspURL, vsCookie); + + list vCookie = cookie.getAllCookie(); + + cout << "All Cookie:" << sRspURL << "-----------------------------------" << endl; + + list::iterator it = vCookie.begin(); + + while(it != vCookie.end()) + { + cout << TC_Common::tostr(it->_data.begin(), it->_data.end(), "; ") << ", " << it->_expires << ", " << it->_path << endl; + + ++it; + } + + cout << "-----------------------------------" << endl << endl; + + string sCookie; + + cookie.getCookieForURL(sReqURL, sCookie); + + cout << TC_Common::tostr(sCookie) << endl; + + cout << "-----------------------------------" << endl << endl; +} + +TEST_F(HttpTest, testCookie) //此时使用的是TEST_F宏 +{ + ASSERT_TRUE(TC_HttpCookie::matchDomain("qq.com", "www.qq.com") == true); + ASSERT_TRUE(TC_HttpCookie::matchDomain(".qq.com", "www.qq.com") == true); + ASSERT_TRUE(TC_HttpCookie::matchDomain(".qq.com", "qq.com") == true); + ASSERT_TRUE(TC_HttpCookie::matchDomain("t.qq.com", "www.qq.com") == false); + ASSERT_TRUE(TC_HttpCookie::matchDomain(".t.qq.com", "www.qq.com") == false); + ASSERT_TRUE(TC_HttpCookie::matchDomain(".t.qq.com", "t.qq.com") == true); + ASSERT_TRUE(TC_HttpCookie::matchDomain(".com", "www.qq.com") == false); + ASSERT_TRUE(TC_HttpCookie::matchDomain(".com", "qq.com") == false); + ASSERT_TRUE(TC_HttpCookie::matchDomain(".y.qq.com", "x.y.qq.com") == true); + ASSERT_TRUE(TC_HttpCookie::matchDomain(".x.y.qq.com", "x.y.qq.com") == true); + ASSERT_TRUE(TC_HttpCookie::matchDomain(".qq.com", "x.y.qq.com") == true); + ASSERT_TRUE(TC_HttpCookie::matchDomain(".qq.com", "y.qq.com") == true); + ASSERT_TRUE(TC_HttpCookie::matchDomain("qq.com", "y.qq.com") == true); + + cout << TC_Common::now2GMTstr() << endl; + + string gmt = TC_Common::tm2GMTstr(time(NULL) + 10); + + string s = "HTTP/1.1 200 OK\r\n";// 200 Aouut Error\r\n"; + s += "Set-Cookie: n1=1; a=1; c=d; Path=/; Domain=qq.com; Expires=" + gmt + "\r\n"; + s += "Set-Cookie: n2=2; a=0; c=d; Path=/abc/def; Domain=.qq.com; Expires=" + gmt + "\r\n"; + s += "Set-Cookie: n3=3; a=5; c=d; Path=/abc/def/aaa; Domain=.qq.com; Expires=" + gmt + "\r\n"; + s += "Set-Cookie: n4=4; a=6; c=d; Path=/abc; Domain=.qq.com; Expires=" + gmt + "\r\n"; + s += "Set-Cookie: n5=5; a=2; c=d; Path=/; Domain=.qq.com; Expires=" + gmt + "\r\n"; + s += "Set-Cookie: n6=6; c=3; Path=/; Domain=y.qq.com; Expires=" + gmt + "\r\n"; + s += "Set-Cookie: n7=7; c=3; Path=/abc; Domain=.y.qq.com; Expires=" + gmt + "\r\n"; + s += "Set-Cookie: n8=6; c=3; Path=/; Domain=x.y.qq.com; Expires=" + gmt + "\r\n"; + s += "Set-Cookie: n9=7; c=4; Path=/; Domain=.x.y.qq.com; Expires=" + gmt + "\r\n"; + s += "Set-Cookie: n10=7; c=4; Path=/; Domain=qqq.com; Expires=" + gmt + "\r\n"; + s += "Set-Cookie: n11=7; c=4; Path=/; Domain=.qqq.com; Expires=" + gmt + "\r\n"; + s += "Set-Cookie: n12=8; c=4; Expires=" + gmt + "\r\n"; + s += "Accept-Ranges: bytes\r\n\r\n"; + + TC_HttpResponse rsp; + rsp.decode(s); + + cout << "-----------------------------------" << endl; + + vector vsCookie = rsp.getSetCookie(); + + cout << TC_Common::tostr(vsCookie.begin(), vsCookie.end(), "\r\n") << endl << endl; + + testCookie("http://www.qq.com", "http://www.qq.com", vsCookie); + testCookie("http://www.qq.com/abc/def", "http://www.qq.com", vsCookie); + testCookie("http://www.qq.com/abc/def", "http://www.qq.com/abc", vsCookie); + + cout << endl; + testCookie("http://www.qq.com", "http://qq.com", vsCookie); + testCookie("http://www.qq.com/abc/def/aaa", "http://www.qq.com/abc/def/aaa", vsCookie); + testCookie("http://www.qq.com/abc/def/aaa", "http://www.qq.com", vsCookie); + testCookie("http://www.qq.com", "http://www.qq.com/abc/def", vsCookie); + testCookie("http://qq.com", "http://qq.com/abc/def", vsCookie); + testCookie("http://qq.com", "http://t.qq.com/abc/def", vsCookie); + testCookie("http://qq.com", "http://y.qq.com/", vsCookie); + testCookie("http://qq.com", "http://y.qq.com/abc", vsCookie); + testCookie("http://x.y.qq.com", "http://x.y.qq.com", vsCookie); +} +// +//void Test_TC_Http::main() +//{ +// testCheckRequestURL(); +// +// testEncodeString(); +// testEncodeVector(); +// testEncodeBuffString(); +// +// testDecodeString(); +// +// testDecodeBuffString(); +// +// testCheckRequestString(); +// testCheckRequestBuff(); +// +// testHttpFinishNoLength(); +// +// testHttpFinish(); +// +// testHttpNoFinish(); +// +// testHttpRequestChunked(); +// +// testHttpResponse(); +// +// testHttpResponseNoFinish(); +// +// testHttpResponseNoLength(); +// +// testHttpResponseIncrementFinish(); +// +// testHttpResponseChunked(); +// +// testHttpRequestChunkedNoFinish(); +// +// testHttpResponseChunkedNoFinish(); +// +//// testWeb("http://www.baidu.com"); +//// testWeb("http://www.httpwatch.com/httpgallery/chunked/chunkedimage.aspx"); +//// testWeb("http://www.qq.com"); +// +//// testCookie(); +//} diff --git a/examples/scripts/run-auth.bat b/examples/scripts/run-auth.bat index fcff41e0de4f6278a48afea1db1d0c11c35bd9fe..4d828d8da06500b7cb61834ee815a758460d08fe 100644 --- a/examples/scripts/run-auth.bat +++ b/examples/scripts/run-auth.bat @@ -2,7 +2,7 @@ echo "run-auth.bat" set EXE_PATH=%1 -set SRC_PATH=%2 +set SRC_PATH=%2\\.. echo %EXE_PATH% %SRC_PATH% diff --git a/examples/scripts/run-auth.sh b/examples/scripts/run-auth.sh index 44026db92c7712347336f712f89d3b7cebb7dd7e..6b76bb13deec5c4727974d8d65aec57d9b075dee 100644 --- a/examples/scripts/run-auth.sh +++ b/examples/scripts/run-auth.sh @@ -3,7 +3,7 @@ echo "run-auth.sh" EXE_PATH=$1 -SRC_PATH=$2 +SRC_PATH=$2/.. echo ${EXE_PATH} ${SRC_PATH} diff --git a/examples/scripts/run-co.bat b/examples/scripts/run-co.bat index e8e02956e90fb63eb08377d800bedf04d05c626a..72ff15044570c2602b51b34e7559fc4cb4d94ce6 100644 --- a/examples/scripts/run-co.bat +++ b/examples/scripts/run-co.bat @@ -2,7 +2,7 @@ echo "run-co.bat" set EXE_PATH=%1 -set SRC_PATH=%2 +set SRC_PATH=%2\\.. echo %EXE_PATH% %SRC_PATH% diff --git a/examples/scripts/run-co.sh b/examples/scripts/run-co.sh index 7d8eef506250c2597dece8f79e59bdebf01e4583..03cf52a2a63e5b5d00bea9d16349c26376aed8ae 100644 --- a/examples/scripts/run-co.sh +++ b/examples/scripts/run-co.sh @@ -3,7 +3,7 @@ echo "run-co.sh" EXE_PATH=$1 -SRC_PATH=$2 +SRC_PATH=$2/.. echo ${EXE_PATH} ${SRC_PATH} diff --git a/examples/scripts/run-custom.bat b/examples/scripts/run-custom.bat index b1878c9367f07cc7c7586fef46edef7bf7561521..fe002b4700b89ca0cccfb9dced97264b0f9fc1de 100644 --- a/examples/scripts/run-custom.bat +++ b/examples/scripts/run-custom.bat @@ -2,7 +2,7 @@ echo "run-push.bat" set EXE_PATH=%1 -set SRC_PATH=%2 +set SRC_PATH=%2\\.. echo %EXE_PATH% %SRC_PATH% diff --git a/examples/scripts/run-custom.sh b/examples/scripts/run-custom.sh index 88d6c47172cc7b5a8570e17a5ee99723abbe1ca0..48d4482771a9c36cf3bbb7fb8236bb0fde7a4563 100644 --- a/examples/scripts/run-custom.sh +++ b/examples/scripts/run-custom.sh @@ -3,7 +3,7 @@ echo "run-custom.sh" EXE_PATH=$1 -SRC_PATH=$2 +SRC_PATH=$2/.. echo ${EXE_PATH} ${SRC_PATH} diff --git a/examples/scripts/run-http.bat b/examples/scripts/run-http.bat index 213aabfce191a1ab4521630d4c8fc032fbb676e8..6c36e6a0b7ade40439d7bce125bb13e526f328cf 100644 --- a/examples/scripts/run-http.bat +++ b/examples/scripts/run-http.bat @@ -2,7 +2,7 @@ echo "run-http.bat" set EXE_PATH=%1 -set SRC_PATH=%2 +set SRC_PATH=%2\\.. echo %EXE_PATH% %SRC_PATH% diff --git a/examples/scripts/run-http.sh b/examples/scripts/run-http.sh index d7c6f72350c50ecef9dec0d1708848764135790e..2f21191ad354e5d42e093364fcc8a524b6849795 100644 --- a/examples/scripts/run-http.sh +++ b/examples/scripts/run-http.sh @@ -3,7 +3,7 @@ echo "run-http.sh" EXE_PATH=$1 -SRC_PATH=$2 +SRC_PATH=$2/.. echo ${EXE_PATH} ${SRC_PATH} @@ -18,7 +18,9 @@ sleep 1 echo "client: ${EXE_PATH}/HttpClient" -${EXE_PATH}/HttpClient --count=10000 --thread=2 --call=basehttp +${EXE_PATH}/HttpClient --count=10000 --thread=2 --call=base +${EXE_PATH}/HttpClient --count=10000 --thread=2 --call=sync +${EXE_PATH}/HttpClient --count=10000 --thread=2 --call=async #${EXE_PATH}/HttpClient --count=10000 --thread=2 --call=synchttp sleep 1 diff --git a/examples/scripts/run-http2.bat b/examples/scripts/run-http2.bat index 4882d8b0746d097a99a4f37726481e3d243958d4..e2b07349bbb0fdebffda0c91d6b45b9dba459826 100644 --- a/examples/scripts/run-http2.bat +++ b/examples/scripts/run-http2.bat @@ -2,7 +2,7 @@ echo "run-http2.bat" set EXE_PATH=%1 -set SRC_PATH=%2 +set SRC_PATH=%2\\.. echo %EXE_PATH% %SRC_PATH% diff --git a/examples/scripts/run-http2.sh b/examples/scripts/run-http2.sh index bed22244e891e45cb75a3b3b4adadcf6625ba80f..7a39e371fd0903fe36080262765a8a5f14c5e661 100644 --- a/examples/scripts/run-http2.sh +++ b/examples/scripts/run-http2.sh @@ -2,7 +2,7 @@ echo "run-http2.sh" EXE_PATH=$1 -SRC_PATH=$2 +SRC_PATH=$2/.. echo ${EXE_PATH} ${SRC_PATH} diff --git a/examples/scripts/run-push.bat b/examples/scripts/run-push.bat index e49a17fe01d863ff4088c5d60e62ad86ef9991c3..5c1afdcfa8772408df916b9074989c020a308ecf 100644 --- a/examples/scripts/run-push.bat +++ b/examples/scripts/run-push.bat @@ -2,7 +2,7 @@ echo "run-push.bat" set EXE_PATH=%1 -set SRC_PATH=%2 +set SRC_PATH=%2\\.. echo %EXE_PATH% %SRC_PATH% diff --git a/examples/scripts/run-push.sh b/examples/scripts/run-push.sh index e77135e62bf727f7598de0a9d1518de3bc4a6236..dfece2bcef5274fde9c1c749d1db711c8dcec0f6 100644 --- a/examples/scripts/run-push.sh +++ b/examples/scripts/run-push.sh @@ -2,7 +2,7 @@ echo "run-co.sh" EXE_PATH=$1 -SRC_PATH=$2 +SRC_PATH=$2/.. echo ${EXE_PATH} ${SRC_PATH} diff --git a/examples/scripts/run-quick-start.bat b/examples/scripts/run-quick-start.bat index 141802debd01dd15d34f64be1d77bafaa4db9e93..a3c02d8f599b63ee3eeaed68880dc8957080881c 100644 --- a/examples/scripts/run-quick-start.bat +++ b/examples/scripts/run-quick-start.bat @@ -2,7 +2,7 @@ echo "run-quick-start.bat" set EXE_PATH=%1 -set SRC_PATH=%2 +set SRC_PATH=%2\\.. echo %EXE_PATH% %SRC_PATH% diff --git a/examples/scripts/run-quick-start.sh b/examples/scripts/run-quick-start.sh index 51d8b7d4d6516d9f1576067f9cd3e472c3837675..d7a2e06c8c8655fea13726e0ec31231c861912b1 100644 --- a/examples/scripts/run-quick-start.sh +++ b/examples/scripts/run-quick-start.sh @@ -2,7 +2,7 @@ echo "run-quick-start.sh" EXE_PATH=$1 -SRC_PATH=$2 +SRC_PATH=$2/.. echo ${EXE_PATH} ${SRC_PATH} diff --git a/examples/scripts/run-ssl.bat b/examples/scripts/run-ssl.bat index 1e8ebdf7e816cb36c8fb972fd409072db10df786..d3214c4ca61c15e57beb2bba9f295dd8af14eeeb 100644 --- a/examples/scripts/run-ssl.bat +++ b/examples/scripts/run-ssl.bat @@ -2,7 +2,7 @@ echo "run-ssl.bat" set EXE_PATH=%1 -set SRC_PATH=%2 +set SRC_PATH=%2\\.. echo %EXE_PATH% %SRC_PATH% diff --git a/examples/scripts/run-ssl.sh b/examples/scripts/run-ssl.sh index be46809a88eb8caabe22c171a248f8910a7f05f7..a7c8f0c6c54a496be08e95ea8826ef2810e7d122 100644 --- a/examples/scripts/run-ssl.sh +++ b/examples/scripts/run-ssl.sh @@ -2,7 +2,7 @@ echo "run-ssl.sh" EXE_PATH=$1 -SRC_PATH=$2 +SRC_PATH=$2/.. echo ${EXE_PATH} ${SRC_PATH} diff --git a/examples/scripts/run-udp.bat b/examples/scripts/run-udp.bat new file mode 100644 index 0000000000000000000000000000000000000000..49e2018792a35b26e3a5f00d4a8ddc6ae1ad3def --- /dev/null +++ b/examples/scripts/run-udp.bat @@ -0,0 +1,30 @@ + +echo "run-auth.bat" + +set EXE_PATH=%1 +set SRC_PATH=%2\\.. + +echo %EXE_PATH% %SRC_PATH% + +taskkill /im UdpServer.exe /t /f + +timeout /T 1 + +echo "start server: %EXE_PATH%/UdpServer.exe --config=%SRC_PATH%/examples/UdpDemo/Server/config.conf" + +start /b %EXE_PATH%\\UdpServer.exe --config=%SRC_PATH%\\examples\\UdpDemo\\Server\\config.conf + +timeout /T 3 + +echo "client: ${EXE_PATH}/UdpClient.exe" + +%EXE_PATH%\\UdpClient.exe --count=10000 --thread=2 --call=sync --buffersize=1000 --netthread=1 +%EXE_PATH%\\UdpClient.exe --count=10000 --thread=2 --call=async --buffersize=1000 --netthread=1 + +timeout /T 1 + +taskkill /im UdpServer.exe /t /f + + + + diff --git a/examples/scripts/run-udp.sh b/examples/scripts/run-udp.sh new file mode 100644 index 0000000000000000000000000000000000000000..79a3be7df0109f02ad5184ecddcf4b3f431d39f2 --- /dev/null +++ b/examples/scripts/run-udp.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +echo "run-auth.sh" + +EXE_PATH=$1 +SRC_PATH=$2/.. + +echo ${EXE_PATH} ${SRC_PATH} + +killall -9 UdpServer + +sleep 1 +echo "start server: ${EXE_PATH}/UdpServer --config=${SRC_PATH}/examples/UdpDemo/Server/config.conf &" + +${EXE_PATH}/UdpServer --config=${SRC_PATH}/examples/UdpDemo/Server/config.conf & + +sleep 1 + +echo "client: ${EXE_PATH}/UdpClient" + +${EXE_PATH}/UdpClient --config=${SRC_PATH}/examples/UdpDemo/Client/config.conf --count=10000 --thread=2 --call=sync --buffersize=1000 --netthread=1 +${EXE_PATH}/UdpClient --config=${SRC_PATH}/examples/UdpDemo/Client/config.conf --count=10000 --thread=2 --call=async --buffersize=1000 --netthread=1 + +sleep 1 + +killall -9 UdpServer + + diff --git a/servant/CMakeLists.txt b/servant/CMakeLists.txt index 992a7f4b62207ad06d17748e71d1caf6d652059d..e377d231acf82cfdf527bf426d8f72bb9ca9f55b 100644 --- a/servant/CMakeLists.txt +++ b/servant/CMakeLists.txt @@ -2,31 +2,31 @@ cmake_minimum_required(VERSION 3.2) project(servant) - -if(_USE_OPENTRACKING) +if(TARS_OPENTRACKING) include_directories(${util_SOURCE_DIR}/include ${OPENTRACKING_INC}) else() include_directories(${util_SOURCE_DIR}/include) endif() -# link_libraries(pthread) - #调用tars2cpp, 生成tars对应的文件 -macro(complice_tars OUT_DEPENDS_LIST HEADER TARS_DIR) +macro(complice_tars OUT_DEPENDS_LIST HEADER INCLUDE) set(DEPENDS_LIST) - if ("${TARS_DIR}" STREQUAL "") - FILE(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/*.tars") - else () - FILE(GLOB SRC_LIST "${TARS_DIR}/*.tars") - endif () + FILE(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/*.tars") set(CLEAN_LIST) #设置tars生成后, cpp文件因为h文件的include路径 - set(INCLUDE) + set(HEADER_STRING) if (NOT "${HEADER}" STREQUAL "") - set(INCLUDE "--header=${HEADER}") + set(HEADER_STRING "--header=${HEADER}") + endif () + + #设置tars文件搜索路径 + set(INCLUDE_STRING "") + set(HEADER_STRING) + if (NOT "${INCLUDE}" STREQUAL "") + set(INCLUDE_STRING "--include=${INCLUDE}") endif () foreach (FILE ${SRC_LIST}) @@ -40,9 +40,9 @@ macro(complice_tars OUT_DEPENDS_LIST HEADER TARS_DIR) add_custom_command( OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${TARS_H} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS tars2cpp - COMMAND ${TARS2CPP} --with-tars ${INCLUDE} ${TARS_IN} - COMMENT "${TARS2CPP} --with-tars ${INCLUDE} ${TARS_IN}") + DEPENDS tars2cpp ${FILE} + COMMAND ${TARS2CPP} --with-tars ${HEADER_STRING} ${INCLUDE_STRING} ${TARS_IN} + COMMENT "${TARS2CPP} --with-tars ${HEADER_STRING} ${INCLUDE_STRING} ${TARS_IN}") list(APPEND DEPENDS_LIST ${CMAKE_CURRENT_SOURCE_DIR}/${TARS_H}) @@ -62,13 +62,15 @@ macro(complice_tars OUT_DEPENDS_LIST HEADER TARS_DIR) endmacro() add_subdirectory(protocol/servant) +add_subdirectory(protocol/framework) add_subdirectory(tup) add_subdirectory(libservant) - install(DIRECTORY servant DESTINATION include) install(DIRECTORY tup DESTINATION include) install(DIRECTORY jmem DESTINATION include) -install(DIRECTORY script DESTINATION .) +install(DIRECTORY script DESTINATION . + PATTERN "*.sh" + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_READ WORLD_EXECUTE) install(DIRECTORY makefile DESTINATION .) diff --git a/servant/libservant/AdapterProxy.cpp b/servant/libservant/AdapterProxy.cpp index 68fb9e83d30d236520a3288b746d46abbaf0f5bf..05b713e9a6fd9d3d5d4a077db837d61f2ffb5c83 100755 --- a/servant/libservant/AdapterProxy.cpp +++ b/servant/libservant/AdapterProxy.cpp @@ -20,13 +20,13 @@ #include "servant/Application.h" #include "servant/AdminF.h" #include "servant/AppCache.h" -#include "servant/TarsLogger.h" +#include "servant/RemoteLogger.h" #include "tup/tup.h" #include "servant/StatF.h" #include "servant/StatReport.h" #include "util/tc_http2.h" // #include "util/tc_http2clientmgr.h" -#ifdef _USE_OPENTRACKING +#ifdef TARS_OPENTRACKING #include "servant/text_map_carrier.h" #endif @@ -50,11 +50,11 @@ AdapterProxy::AdapterProxy(ObjectProxy * pObjectProxy,const EndpointInfo &ep,Com , _connTimeout(false) , _connExc(false) , _connExcCnt(0) -, _staticWeight(0) +//, _staticWeight(0) , _timeoutLogFlag(false) , _noSendQueueLimit(1000) -, _maxSampleCount(1000) -, _sampleRate(0) +//, _maxSampleCount(1000) +//, _sampleRate(0) , _id((++_idGen)) { _timeoutQueue.reset(new TC_TimeoutQueueNew()); @@ -64,10 +64,10 @@ AdapterProxy::AdapterProxy(ObjectProxy * pObjectProxy,const EndpointInfo &ep,Com _noSendQueueLimit = pObjectProxy->getCommunicatorEpoll()->getNoSendQueueLimit(); } - if(_communicator) - { - _timeoutLogFlag = _communicator->getTimeoutLogFlag(); - } + // if(_communicator) + // { + // _timeoutLogFlag = pObjectProxy->getCommunicatorEpoll()->getTimeoutLogFlag(); + // } if (ep.isTcp()) { @@ -92,7 +92,6 @@ AdapterProxy::~AdapterProxy() // adapterProxy->checkActive(true); // return adapterProxy; //} - string AdapterProxy::getSlaveName(const string& sSlaveName) { string::size_type pos = sSlaveName.find("."); @@ -110,78 +109,125 @@ string AdapterProxy::getSlaveName(const string& sSlaveName) void AdapterProxy::initStatHead() { - vector v; - if(!ClientConfig::SetDivision.empty() && - StatReport::divison2SetInfo(ClientConfig::SetDivision, v)) //主调(client)启用set - { - _statHead.masterName = StatReport::trimAndLimitStr(ClientConfig::ModuleName + "." + v[0] + v[1] + v[2] + "@" + ClientConfig::TarsVersion, StatReport::MAX_MASTER_NAME_LEN); - } - else - { - _statHead.masterName = StatReport::trimAndLimitStr(ClientConfig::ModuleName + "@" + ClientConfig::TarsVersion, StatReport::MAX_MASTER_NAME_LEN); - } - - const string sSlaveName = getSlaveName(_objectProxy->name()); - string sSlaveSet = _endpoint.setDivision(); - if(!sSlaveSet.empty() && - StatReport::divison2SetInfo(sSlaveSet, v)) //被调启用set - { - _statHead.slaveSetName = v[0]; - _statHead.slaveSetArea = v[1]; - _statHead.slaveSetID = v[2]; - _statHead.slaveName = StatReport::trimAndLimitStr(sSlaveName + "." + v[0] + v[1] + v[2], StatReport::MAX_MASTER_NAME_LEN); - } - else - { - _statHead.slaveName = StatReport::trimAndLimitStr(sSlaveName, StatReport::MAX_MASTER_NAME_LEN); - } + vector v; + if(!ClientConfig::SetDivision.empty() && + StatReport::divison2SetInfo(ClientConfig::SetDivision, v)) //主调(client)启用set + { + _statHead.masterName = StatReport::trimAndLimitStr(ClientConfig::ModuleName + "." + v[0] + v[1] + v[2] + "@" + ClientConfig::TarsVersion, StatReport::MAX_MASTER_NAME_LEN); + } + else + { + _statHead.masterName = StatReport::trimAndLimitStr(ClientConfig::ModuleName + "@" + ClientConfig::TarsVersion, StatReport::MAX_MASTER_NAME_LEN); + } + + const string sSlaveName = getSlaveName(_objectProxy->name()); + string sSlaveSet = _endpoint.setDivision(); + if(!sSlaveSet.empty() && + StatReport::divison2SetInfo(sSlaveSet, v)) //被调启用set + { + _statHead.slaveSetName = v[0]; + _statHead.slaveSetArea = v[1]; + _statHead.slaveSetID = v[2]; + _statHead.slaveName = StatReport::trimAndLimitStr(sSlaveName + "." + v[0] + v[1] + v[2], StatReport::MAX_MASTER_NAME_LEN); + } + else + { + _statHead.slaveName = StatReport::trimAndLimitStr(sSlaveName, StatReport::MAX_MASTER_NAME_LEN); + } + + _statHead.slaveIp = StatReport::trimAndLimitStr(_endpoint.host(), StatReport::MAX_MASTER_IP_LEN); + _statHead.slavePort = _endpoint.port(); + _statHead.returnValue = 0; +} + +//bool AdapterProxy::invoke_sync(ReqMessage * msg) +//{ +// if(!_trans->hasConnected()) { +// TLOGTARS("[AdapterProxy::invoke_sync " << _objectProxy->name() << ", " << _endpoint.desc() << "]" << endl); +// return false; +// } +// +// //生成requestid +// //taf调用 而且 不是单向调用 +// if (!msg->bFromRpc) +// { +// // msg->request.iRequestId = _objectProxy->generateId(); +// msg->request.iRequestId = _timeoutQueue->generateId(); +// } +// +// msg->sReqData->setBuffer(_objectProxy->getProxyProtocol().requestFunc(msg->request, _trans)); +// +// msg->response = std::make_shared(); +// +// //这里得加锁 +// std::lock_guard lock(_mutex); +// +// _trans->sendRecv(msg); +// +// return true; +//} - _statHead.slaveIp = StatReport::trimAndLimitStr(_endpoint.host(), StatReport::MAX_MASTER_IP_LEN); - _statHead.slavePort = _endpoint.port(); - _statHead.returnValue = 0; +void AdapterProxy::onConnect() +{ + _objectProxy->onConnect(this); } -int AdapterProxy::invoke(ReqMessage * msg) +int AdapterProxy::invoke_connection_serial(ReqMessage * msg) { - assert(_trans != NULL); + assert(msg->eType != ReqMessage::ONE_WAY); - TLOGTARS("[TARS][AdapterProxy::invoke objname:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << endl); + msg->sReqData->setBuffer(_objectProxy->getProxyProtocol().requestFunc(msg->request, _trans.get())); - //未发链表有长度限制 - if(_timeoutQueue->getSendListSize() >= _noSendQueueLimit) - { - TLOGERROR("[TARS][AdapterProxy::invoke fail,ReqInfoQueue.size > " << _noSendQueueLimit << ",objname:" << _objectProxy->name() <<",desc:"<< _endpoint.desc() << endl); - msg->eStatus = ReqMessage::REQ_EXC; + msg->request.iRequestId = _timeoutQueue->generateId(); - finishInvoke(msg); + if(!_requestMsg && _timeoutQueue->sendListEmpty() && _trans->sendRequest(msg->sReqData) != Transceiver::eRetError) + { + TLOGTARS("[AdapterProxy::invoke push (send) obj: " << _objectProxy->name() << ", desc:" << _endpoint.desc() << ", id: " << msg->request.iRequestId << endl); - return 0; - } + _requestMsg = msg; - //生成requestid - //tars调用 而且 不是单向调用 - if(!msg->bFromRpc) - { - msg->request.iRequestId = _timeoutQueue->generateId(); - } + bool bFlag = _timeoutQueue->push(msg, msg->request.iRequestId, msg->request.iTimeout + msg->iBeginTime); + if (!bFlag) + { + TLOGERROR("[AdapterProxy::invoke fail1 : insert timeout queue fail,queue size:" << _timeoutQueue->size() << ",id: " << msg->request.iRequestId << "," << _objectProxy->name() << ", " << _endpoint.desc() << "]" << endl); + msg->eStatus = ReqMessage::REQ_EXC; -#ifdef _USE_OPENTRACKING - startTrack(msg); -#endif + finishInvoke(msg); + } + } + else + { + TLOGTARS("[AdapterProxy::invoke push (no send) " << _objectProxy->name() << ", " << _endpoint.desc() << ",id " << msg->request.iRequestId << endl); + + //之前还没有数据没发送 或者 请求发送失败了, 进队列 + bool bFlag = _timeoutQueue->push(msg, msg->request.iRequestId, msg->request.iTimeout + msg->iBeginTime, false); + if (!bFlag) + { + TLOGERROR("[AdapterProxy::invoke fail2 : insert timeout queue fail,queue size:" << _timeoutQueue->size() << ", id: " << msg->request.iRequestId << ", " << _objectProxy->name() << ", " << _endpoint.desc() << "]" << endl); + msg->eStatus = ReqMessage::REQ_EXC; - msg->sReqData->setBuffer(_objectProxy->getProxyProtocol().requestFunc(msg->request, _trans.get())); + finishInvoke(msg); + } + } -// TLOGERROR("[TARS][AdapterProxy::invoke insert timeout queue fail, queue size:" << _timeoutQueue->size() << ", id:" << msg->request.iRequestId << ", obj:" <<_objectProxy->name() << ", desc:" << _endpoint.desc() <sReqData->setBuffer(_objectProxy->getProxyProtocol().requestFunc(msg->request, _trans.get())); + +// TLOGERROR("[AdapterProxy::invoke insert timeout queue fail, queue size:" << _timeoutQueue->size() << ", id:" << msg->request.iRequestId << ", obj:" <<_objectProxy->name() << ", desc:" << _endpoint.desc() <sendListEmpty() && _trans->sendRequest(msg->sReqData) != Transceiver::eRetError) { - TLOGTARS("[TARS][AdapterProxy::invoke push (send) obj:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ",id:" << msg->request.iRequestId << endl); + TLOGTARS("[AdapterProxy::invoke push (send) obj:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ",id:" << msg->request.iRequestId << endl); //请求发送成功了,单向调用直接返回 if(msg->eType == ReqMessage::ONE_WAY) { - #ifdef _USE_OPENTRACKING + #ifdef TARS_OPENTRACKING finishTrack(msg); #endif @@ -194,7 +240,7 @@ int AdapterProxy::invoke(ReqMessage * msg) bool bFlag = _timeoutQueue->push(msg, msg->request.iRequestId, msg->request.iTimeout + msg->iBeginTime); if(!bFlag) { - TLOGERROR("[TARS][AdapterProxy::invoke fail1: insert timeout queue fail, queue size:" << _timeoutQueue->size() << ", id:" << msg->request.iRequestId << ", obj:" <<_objectProxy->name() << ", desc:" << _endpoint.desc() <size() << ", id:" << msg->request.iRequestId << ", obj:" <<_objectProxy->name() << ", desc:" << _endpoint.desc() <eStatus = ReqMessage::REQ_EXC; finishInvoke(msg); @@ -204,13 +250,13 @@ int AdapterProxy::invoke(ReqMessage * msg) } else { - TLOGTARS("[TARS][AdapterProxy::invoke push (no send) " << _objectProxy->name() << ", " << _endpoint.desc() << ",id:" << msg->request.iRequestId <name() << ", " << _endpoint.desc() << ",id:" << msg->request.iRequestId <push(msg,msg->request.iRequestId, msg->request.iTimeout+msg->iBeginTime, false); if(!bFlag) { - TLOGERROR("[TARS][AdapterProxy::invoke fail2: insert timeout queue fail, queue size:" << _timeoutQueue->size() << ", id:" << msg->request.iRequestId << ", obj:" <<_objectProxy->name() << ", desc:" << _endpoint.desc() <size() << ", id:" << msg->request.iRequestId << ", obj:" <<_objectProxy->name() << ", desc:" << _endpoint.desc() <eStatus = ReqMessage::REQ_EXC; @@ -218,32 +264,128 @@ int AdapterProxy::invoke(ReqMessage * msg) } } -#ifdef _USE_OPENTRACKING - if(msg->eType == ReqMessage::ONE_WAY) + return 0; +} + +int AdapterProxy::invoke(ReqMessage * msg) +{ + assert(_trans != NULL); + + TLOGTARS("[AdapterProxy::invoke " << _objectProxy->name() << ", " << _endpoint.desc() << "]" << endl); + + //未发链表有长度限制 + if (_timeoutQueue->getSendListSize() >= _noSendQueueLimit) { - finishTrack(msg); + TLOGERROR("[AdapterProxy::invoke fail,ReqInfoQueue.size>" << _noSendQueueLimit << "," << _objectProxy->name() << "," << _endpoint.desc() << "]" << endl); + msg->eStatus = ReqMessage::REQ_EXC; + + finishInvoke(msg); + return 0; } -#endif - return 0; + + //生成requestid + //taf调用 而且 不是单向调用 + if (!msg->bFromRpc) + { + msg->request.iRequestId = _timeoutQueue->generateId(); + } + + if(_objectProxy->getServantProxy()->tars_connection_serial() > 0) + { + invoke_connection_serial(msg); + } + else + { + invoke_connection_parallel(msg); + } +// +// msg->sReqData->setBuffer(_objectProxy->getProxyProtocol().requestFunc(msg->request, _trans.get())); +// +// //当前队列是空的, 且是连接复用模式, 交给连接发送数据 +// //连接连上 buffer不为空 发送数据成功 +// if (_timeoutQueue->sendListEmpty() && _trans->sendRequest(msg->sReqData) != Transceiver::eRetError) +// { +// TLOGTARS("[AdapterProxy::invoke push (send) obj: " << _objectProxy->name() << ", desc:" << _endpoint.desc() << ", id: " << msg->request.iRequestId << endl); +// +// //请求发送成功了 处理采样 +// //这个请求发送成功了。单向调用直接返回 +// if (msg->eType == ReqMessage::ONE_WAY) +// { +// delete msg; +// msg = NULL; +// +// return 0; +// } +// +// bool bFlag = _timeoutQueue->push(msg, msg->request.iRequestId, msg->request.iTimeout + msg->iBeginTime); +// if (!bFlag) +// { +// TLOGERROR("[AdapterProxy::invoke fail1 : insert timeout queue fail,queue size:" << _timeoutQueue->size() << ",id: " << msg->request.iRequestId << "," << _objectProxy->name() << ", " << _endpoint.desc() << "]" << endl); +// msg->eStatus = ReqMessage::REQ_EXC; +// +// finishInvoke(msg); +// } +// } +// else +// { +// TLOGTARS("[AdapterProxy::invoke push (no send) " << _objectProxy->name() << ", " << _endpoint.desc() << ",id " << msg->request.iRequestId << endl); +// +// //之前还没有数据没发送 或者 请求发送失败了, 进队列 +// bool bFlag = _timeoutQueue->push(msg, msg->request.iRequestId, msg->request.iTimeout + msg->iBeginTime, false); +// if (!bFlag) +// { +// TLOGERROR("[AdapterProxy::invoke fail2 : insert timeout queue fail,queue size:" << _timeoutQueue->size() << ", id: " << msg->request.iRequestId << ", " << _objectProxy->name() << ", " << _endpoint.desc() << "]" << endl); +// msg->eStatus = ReqMessage::REQ_EXC; +// +// finishInvoke(msg); +// } +// } + + return 0; } -void AdapterProxy::doInvoke() +void AdapterProxy::doInvoke_serial() { - while(!_timeoutQueue->sendListEmpty()) - { - ReqMessage * msg = NULL; + assert(_requestMsg == NULL); + + if(!_timeoutQueue->sendListEmpty()) + { + ReqMessage * msg = NULL; + + _timeoutQueue->getSend(msg); + + int iRet = _trans->sendRequest(msg->sReqData); + + //发送失败 返回 + if (iRet == Transceiver::eRetError) + { + TLOGTARS("[AdapterProxy::doInvoke sendRequest failed, obj:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ",id:" << msg->request.iRequestId << ", ret:" << iRet << endl); + return; + } + + //送send 队列中清掉, 但是保留在定时队列中 + _timeoutQueue->popSend(false); - _timeoutQueue->getSend(msg); + _requestMsg = msg; + } +} + +void AdapterProxy::doInvoke_parallel() +{ + while(!_timeoutQueue->sendListEmpty()) + { + ReqMessage * msg = NULL; + + _timeoutQueue->getSend(msg); - int iRet = _trans->sendRequest(msg->sReqData); + int iRet = _trans->sendRequest(msg->sReqData); //发送失败 返回 if(iRet == Transceiver::eRetError) { - TLOGTARS("[TARS][AdapterProxy::doInvoke sendRequest failed, obj:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ",id:" << msg->request.iRequestId << ", ret:" << iRet << endl); + TLOGTARS("[AdapterProxy::doInvoke sendRequest failed, obj:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ",id:" << msg->request.iRequestId << ", ret:" << iRet << endl); return; } - TLOGTARS("[TARS][AdapterProxy::doInvoke sendRequest obj:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ",id:" << msg->request.iRequestId << ",ret:" << iRet << endl); //请求发送成功了 处理采样 //... @@ -264,10 +406,24 @@ void AdapterProxy::doInvoke() } } +void AdapterProxy::doInvoke(bool initInvoke) +{ + if(_objectProxy->getServantProxy()->tars_connection_serial() > 0) + { + if(initInvoke) + { + doInvoke_serial(); + } + } + else + { + doInvoke_parallel(); + } +} void AdapterProxy::finishInvoke(bool bFail) { - TLOGTARS("[TARS][AdapterProxy::finishInvoke(bool) obj:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ",bFail:" << bFail << endl); + TLOGTARS("[AdapterProxy::finishInvoke(bool) obj:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ",bFail:" << bFail << endl); time_t now = TNOW; @@ -296,12 +452,12 @@ void AdapterProxy::finishInvoke(bool bFail) _connExc = false; - TLOGTARS("[TARS][AdapterProxy::finishInvoke(bool), objname:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ",retry ok" << endl); + TLOGTARS("[AdapterProxy::finishInvoke(bool), objname:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ",retry ok" << endl); } else { //结点已经屏蔽 过来失败的包不用处理 - TLOGTARS("[TARS][AdapterProxy::finishInvoke(bool), objname:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ",retry fail" << endl); + TLOGTARS("[AdapterProxy::finishInvoke(bool), objname:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ",retry fail" << endl); } return; } @@ -331,7 +487,7 @@ void AdapterProxy::finishInvoke(bool bFail) _activeStatus = false; _nextRetryTime = TNOW + _objectProxy->checkTimeoutInfo().tryTimeInterval; - TLOGERROR("[TARS][AdapterProxy::finishInvoke(bool) objname:"<< _objectProxy->name() + TLOGERROR("[AdapterProxy::finishInvoke(bool) objname:"<< _objectProxy->name() << ",desc:" << _endpoint.desc() << ",disable frequenceFail,freqtimeout:" << _frequenceFailInvoke << ",timeout:"<< _timeoutInvoke @@ -352,7 +508,7 @@ void AdapterProxy::finishInvoke(bool bFail) if(bFail && _timeoutInvoke >= info.minTimeoutInvoke && _timeoutInvoke >= info.radio * _totalInvoke) { setInactive(); - TLOGERROR("[TARS][AdapterProxy::finishInvoke(bool) objname" << _objectProxy->name() + TLOGERROR("[AdapterProxy::finishInvoke(bool) objname" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ",disable radioFail,freqtimeout:" << _frequenceFailInvoke << ",timeout:"<< _timeoutInvoke @@ -375,9 +531,15 @@ int AdapterProxy::getConTimeout() bool AdapterProxy::checkActive(bool bForceConnect, bool onlyCheck) { - time_t now = TNOW; - - TLOGTARS("[TARS][AdapterProxy::checkActive objname:" << _objectProxy->name() + if(onlyCheck) + { + return _trans->hasConnected(); + } + else + { + time_t now = TNOW; + + TLOGTARS("[AdapterProxy::checkActive objname:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ",_activeStatus:" << (_activeStatus ? "enable" : "disable") << (bForceConnect? ",forceConnect" : "") @@ -416,7 +578,7 @@ bool AdapterProxy::checkActive(bool bForceConnect, bool onlyCheck) _trans->close(); - TLOGERROR("[TARS][AdapterProxy::checkActive connect objname:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ", ex:" << ex.what() << endl); + TLOGERROR("[AdapterProxy::checkActive connect objname:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ", ex:" << ex.what() << endl); } } @@ -426,7 +588,7 @@ bool AdapterProxy::checkActive(bool bForceConnect, bool onlyCheck) //失效且没有到下次重试时间, 直接返回不可用 if((!_activeStatus) && (now < _nextRetryTime) ) { - TLOGTARS("[TARS][AdapterProxy::checkActive,not reach retry time ,objname:" << _objectProxy->name() << ",desc:" << _endpoint.desc() <name() << ",desc:" << _endpoint.desc() <close(); - TLOGERROR("[TARS][AdapterProxy::checkActive connect objname:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ", ex:" << ex.what() << endl); + TLOGERROR("[AdapterProxy::checkActive connect objname:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ", ex:" << ex.what() << endl); } } - return _trans->hasConnected(); + //已经建立连接了才返回 + return _trans->hasConnected(); + } } - void AdapterProxy::setConTimeout(bool bConTimeout) { if(bConTimeout != _connTimeout) { - TLOGERROR("[TARS][AdapterProxy::setConTimeout desc:"<< _endpoint.desc() << " connect timeout status is:" << bConTimeout << endl); + TLOGERROR("[AdapterProxy::setConTimeout desc:"<< _endpoint.desc() << " connect timeout status is:" << bConTimeout << endl); _connTimeout = bConTimeout; if(_connTimeout) { @@ -469,31 +632,77 @@ void AdapterProxy::setConTimeout(bool bConTimeout) } } +void AdapterProxy::onSetInactive() +{ + _activeStatus = false; + + _nextRetryTime = TNOW + _objectProxy->checkTimeoutInfo().tryTimeInterval; + + //需要关闭连接 + _trans->close(); +} + //屏蔽结点 void AdapterProxy::setInactive() { - _activeStatus = false; + onSetInactive(); + + _objectProxy->getServantProxy()->onSetInactive(_endpoint); + + TLOGTARS("[AdapterProxy::setInactive, " << _objectProxy->name() << ", " << _endpoint.desc() << ", inactive]" << endl); +} + +void AdapterProxy::finishInvoke_serial(shared_ptr & rsp) +{ + TLOGTARS("[AdapterProxy::finishInvoke(ResponsePacket), " << _objectProxy->name() << ", " << _endpoint.desc() << ", id:" << rsp->iRequestId << "]" << endl); + + if (!_requestMsg) + { + if(_timeoutLogFlag) + { + TLOGERROR("[AdapterProxy::finishInvoke(ResponsePacket)," + << _objectProxy->name() + << ",get req-ptr NULL,may be timeout,id:" + << rsp->iRequestId << ",desc:" << _endpoint.desc() << "]" << endl); + } + return; + } - _nextRetryTime = TNOW + _objectProxy->checkTimeoutInfo().tryTimeInterval; + ReqMessage * msg = _requestMsg; - _trans->close(); + //这里的队列中的发送链表中的数据可能已经在timeout的时候删除了,因此可能会core,在erase中要加判断 + //获取请求信息 + bool retErase = _timeoutQueue->erase(_requestMsg->request.iRequestId, msg); - TLOGTARS("[TARS][AdapterProxy::setInactive objname:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ",inactive" << endl); + assert(retErase); + assert(_requestMsg == msg); + assert(msg->eType != ReqMessage::ONE_WAY); + assert(msg->eStatus == ReqMessage::REQ_REQ); + + _requestMsg = NULL; + + msg->eStatus = ReqMessage::REQ_RSP; + + msg->response = rsp; + + finishInvoke(msg); + + //检查连接状态 + checkActive(); } -void AdapterProxy::finishInvoke(shared_ptr & rsp) +void AdapterProxy::finishInvoke_parallel(shared_ptr & rsp) { -// TLOGTARS("[TARS][AdapterProxy::finishInvoke(ResponsePacket) obj:" << _objectProxy->name() << ", desc:" << _endpoint.desc() -// << ", id:" << rsp->iRequestId << endl); + TLOGTARS("[AdapterProxy::finishInvoke(ResponsePacket), " << _objectProxy->name() << ", " << _endpoint.desc() << ", id:" << rsp->iRequestId << "]" << endl); - ReqMessage * msg = NULL; + ReqMessage * msg = NULL; //requestid 为0 是push消息 if(rsp->iRequestId == 0) { if(!_objectProxy->getPushCallback()) { - TLOGERROR("[TARS][AdapterProxy::finishInvoke(ResponsePacket),request id is 0, pushcallback is null, objname:" << _objectProxy->name() + TLOGERROR("[AdapterProxy::finishInvoke(ResponsePacket),request id is 0, pushcallback is null, objname:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << endl); return; } @@ -518,7 +727,7 @@ void AdapterProxy::finishInvoke(shared_ptr & rsp) { if(_timeoutLogFlag) { - TLOGERROR("[TARS][AdapterProxy::finishInvoke(ResponsePacket) obj:"<< _objectProxy->name() << ",get req-ptr NULL,may be timeout,id:" << rsp->iRequestId + TLOGERROR("[AdapterProxy::finishInvoke(ResponsePacket) obj:"<< _objectProxy->name() << ",get req-ptr NULL,may be timeout,id:" << rsp->iRequestId << ",desc:" << _endpoint.desc() << endl); } return ; @@ -534,16 +743,80 @@ void AdapterProxy::finishInvoke(shared_ptr & rsp) finishInvoke(msg); } +void AdapterProxy::finishInvoke(shared_ptr & rsp) +{ + TLOGTARS("[AdapterProxy::finishInvoke(ResponsePacket), " << _objectProxy->name() << ", " << _endpoint.desc() << ", id:" << rsp->iRequestId << "]" << endl); + + if(_objectProxy->getServantProxy()->tars_connection_serial() > 0) + { + finishInvoke_serial(rsp); + } + else + { + finishInvoke_parallel(rsp); + } +// +// ReqMessage * msg = NULL; +// +// if (rsp->iRequestId == 0) +// { +// //requestid 为0 是push消息 +// // +// //push callback is null +// if (!_objectProxy->getPushCallback()) +// { +// TLOGERROR("[AdapterProxy::finishInvoke(ResponsePacket), request id is 0, pushcallback is null, " << _objectProxy->name() << ", " << _endpoint.desc() << "]" << endl); +// return; +// } +// msg = new ReqMessage(); +// msg->eStatus = ReqMessage::REQ_RSP; +// msg->eType = ReqMessage::ASYNC_CALL; +// msg->bFromRpc = true; +// msg->bPush = true; +// msg->proxy = _objectProxy->getServantProxy(); +// msg->pObjectProxy = _objectProxy; +// msg->adapter = this; +// msg->callback = _objectProxy->getPushCallback(); +// } +// else +// { +// //这里的队列中的发送链表中的数据可能已经在timeout的时候删除了,因此可能会core,在erase中要加判断 +// //获取请求信息 +// bool retErase = _timeoutQueue->erase(rsp->iRequestId, msg); +// +// //找不到此id信息 +// if (!retErase) +// { +// if (_timeoutLogFlag) +// { +// TLOGERROR("[AdapterProxy::finishInvoke(ResponsePacket)," +// << _objectProxy->name() +// << ",get req-ptr NULL,may be timeout,id:" +// << rsp->iRequestId << ",desc:" << _endpoint.desc() << "]" << endl); +// } +// return ; +// } +// +// assert(msg->eStatus == ReqMessage::REQ_REQ); +// +// msg->eStatus = ReqMessage::REQ_RSP; +// } +// +// msg->response = rsp; +// +// finishInvoke(msg); +} + void AdapterProxy::finishInvoke(ReqMessage * msg) { assert(msg->eStatus != ReqMessage::REQ_REQ); - TLOGTARS("[TARS][AdapterProxy::finishInvoke(ReqMessage) obj:" << _objectProxy->name() << ", desc:" << _endpoint.desc() + TLOGTARS("[AdapterProxy::finishInvoke(ReqMessage) obj:" << _objectProxy->name() << ", desc:" << _endpoint.desc() << " ,id:" << msg->response->iRequestId << ", status:" << msg->eStatus << ", ret: " << msg->response->iRet << endl); -#ifdef _USE_OPENTRACKING +#ifdef TARS_OPENTRACKING finishTrack(msg); #endif @@ -595,17 +868,15 @@ void AdapterProxy::finishInvoke(ReqMessage * msg) ReqMessagePtr msgPtr = msg; try { - msg->callback->onDispatch(msgPtr); + msg->callback->dispatch(msgPtr); } catch (exception & e) { - //FDLOG("taferror")<<"[TAF]AdapterProxy::finishInvoke(ReqMessage) exp:"<name() << ",desc:" << _endpoint.desc() + TLOGERROR("[AdapterProxy::finishInvoke(ReqMessage) coro parallel callback error,obj:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ",id:" << msg->response->iRequestId << endl); delete msg; msg = NULL; @@ -641,19 +912,21 @@ void AdapterProxy::finishInvoke(ReqMessage * msg) return; } -//ObjectProxy * AdapterProxy::getObjProxy() -//{ -// return _objectProxy; -//} - void AdapterProxy::doTimeout() { ReqMessage * msg; while(_timeoutQueue->timeout(msg)) { - TLOGTARS("[TARS][AdapterProxy::doTimeout obj:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ",id " << msg->request.iRequestId << endl); + TLOGTARS("[AdapterProxy::doTimeout obj:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << ",id " << msg->request.iRequestId << endl); - assert(msg->eStatus == ReqMessage::REQ_REQ); +// assert(msg->eStatus == ReqMessage::REQ_REQ); + + if(msg == _requestMsg) + { + _requestMsg = NULL; + //timeout, close + _trans->close(); + } msg->eStatus = ReqMessage::REQ_TIME; @@ -677,12 +950,12 @@ void AdapterProxy::doTimeout() } -#ifdef _USE_OPENTRACKING +#ifdef TARS_OPENTRACKING void AdapterProxy::startTrack(ReqMessage * msg) { if(!_communicator->_traceManager) { - TLOGTARS("[TARS]tracer info is null, just return" << endl); + TLOGTARS("tracer info is null, just return" << endl); return; } @@ -749,7 +1022,7 @@ void AdapterProxy::stat(ReqMessage * msg) { return ; } - TLOGTARS("[TARS]AdapterProxy::stat(ReqMessage) " << _objectProxy->name() << ", " << _endpoint.desc() << " ,id:" << msg->response->iRequestId << endl); + TLOGTARS("AdapterProxy::stat(ReqMessage) " << _objectProxy->name() << ", " << _endpoint.desc() << " ,id:" << msg->response->iRequestId << endl); StatMicMsgBody body; int64_t sptime = 0; @@ -784,14 +1057,14 @@ void AdapterProxy::stat(ReqMessage * msg) _statBody[msg->request.sFuncName] = body; } - if(LOG->isNeedLog(TarsRollLogger::INFO_LOG)) + if(LOG->isNeedLog(LocalRollLogger::INFO_LOG)) { ostringstream os; os.str(""); _statHead.displaySimple(os); os << " "; _statBody[msg->request.sFuncName].displaySimple(os); - TLOGTARS("[TARS][AdapterProxy::stat(ReqMessage) display:" << os.str() << endl); + TLOGTARS("[AdapterProxy::stat(ReqMessage) display:" << os.str() << endl); } } @@ -818,7 +1091,7 @@ void AdapterProxy::merge(const StatMicMsgBody& inBody,StatMicMsgBody& outBody/*o void AdapterProxy::mergeStat(map & mStatMicMsg) { - TLOGTARS("[TARS][AdapterProxy::doStat obj:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << endl); + TLOGTARS("[AdapterProxy::doStat obj:" << _objectProxy->name() << ",desc:" << _endpoint.desc() << endl); for (const auto& kv : _statBody) { @@ -849,10 +1122,9 @@ void AdapterProxy::addConnExc(bool bExc) { if(!_connExc && _connExcCnt++ >= _objectProxy->checkTimeoutInfo().maxConnectExc) { - if(!_connExc) - { - TLOGERROR("[TARS][AdapterProxy::addConnExc desc:"<< _endpoint.desc() << ",connect exception status is true! (connect error)"<report("AdminServant::notify:" + command); + RemoteNotify::getInstance()->report("AdminServant::notify:" + command); return NotifyObserver::getInstance()->notify(command, current); } diff --git a/servant/libservant/AppProtocol.cpp b/servant/libservant/AppProtocol.cpp index d6af6c132aaff84355f4d6b16571f36202fcfcf4..881ad504f36d3d8d30e81f93f1757454b9f64204 100644 --- a/servant/libservant/AppProtocol.cpp +++ b/servant/libservant/AppProtocol.cpp @@ -19,7 +19,7 @@ #include "servant/AppProtocol.h" #include "servant/Transceiver.h" #include "servant/AdapterProxy.h" -#include "servant/TarsLogger.h" +#include "servant/RemoteLogger.h" #include "tup/Tars.h" #include @@ -60,64 +60,136 @@ vector ProxyProtocol::tarsRequest(RequestPacket& request, Transceiver *) vector ProxyProtocol::http1Request(tars::RequestPacket& request, Transceiver *trans) { - request.iRequestId = trans->getAdapterProxy()->getId(); +// assert(trans->getAdapterProxy()->getObjProxy()->getServantProxy()->taf_connection_serial() > 0); - TC_HttpRequest httpRequest; +// request.iRequestId = trans->getAdapterProxy()->getId(); - httpRequest.setRequest(request.sFuncName, request.sServantName, string(request.sBuffer.data(), request.sBuffer.size()), true); + shared_ptr &data = *(shared_ptr*)request.sBuffer.data(); - vector buffer; + vector buffer; - httpRequest.encode(buffer); + data->encode(buffer); - return buffer; -} - -struct Http1Context -{ - string buff; + data.reset(); - TC_HttpResponse httpRsp; -}; + return buffer; +} TC_NetWorkBuffer::PACKET_TYPE ProxyProtocol::http1Response(TC_NetWorkBuffer &in, ResponsePacket& rsp) { - Http1Context *context = (Http1Context*)(in.getContextData()); + shared_ptr *context = (shared_ptr*)(in.getContextData()); - if(context == NULL) + if(!context) { - context = new Http1Context(); + context = new shared_ptr(); + *context = std::make_shared(); in.setContextData(context, [=]{ delete context; }); } - context->buff.append(in.getBuffersString()); - in.clearBuffers(); - - if(context->httpRsp.incrementDecode(context->buff)) + if((*context)->incrementDecode(in)) { - rsp.iRequestId = ((Transceiver*)(in.getConnection()))->getAdapterProxy()->getId(); + rsp.sBuffer.resize(sizeof(shared_ptr)); - rsp.status["status"] = context->httpRsp.getResponseHeaderLine(); - for (const auto& kv : context->httpRsp.getHeaders()) - { - rsp.status[kv.first] = kv.second; - } + shared_ptr &data = *(shared_ptr*)rsp.sBuffer.data(); - rsp.sBuffer.assign(context->httpRsp.getContent().begin(), context->httpRsp.getContent().end()); + data = *context; - delete context; + if(!data->checkHeader("Connection", "keep-alive")) + { + Transceiver* session = (Transceiver*)(in.getConnection()); - context = NULL; + session->close(); + } - in.setContextData(NULL); + (*context) = NULL; + delete context; + in.setContextData(NULL); - return TC_NetWorkBuffer::PACKET_FULL; + return TC_NetWorkBuffer::PACKET_FULL; } return TC_NetWorkBuffer::PACKET_LESS; } +///////////////////////////////////////////////////////////////////////////////////////////////// + +// vector ProxyProtocol::httpJceRequest(taf::BasePacket& request, Transceiver *trans) +// { +// TC_HttpRequest httpRequest; + +// string uri; +// if(trans->isSSL()) +// uri = "https://"; +// else +// uri = "http://"; + +// uri += trans->getEndpointInfo().getEndpoint().getHost(); + +// vector buff = tafRequest(request, trans); + +// for(auto it = request.context.begin(); it != request.context.end(); ++it) +// { +// if(it->second == ":path") +// { +// uri += "/" + it->second; +// } +// else +// { +// httpRequest.setHeader(it->first, it->second); +// } +// } + +// httpRequest.setPostRequest(uri, buff.data(), buff.size(), true); + +// vector buffer; + +// httpRequest.encode(buffer); + +// return buffer; +// } + +// TC_NetWorkBuffer::PACKET_TYPE ProxyProtocol::httpJceResponse(TC_NetWorkBuffer &in, BasePacket& rsp) +// { +// TC_HttpResponse *context = (TC_HttpResponse*)(in.getContextData()); + +// if(!context) +// { +// context = new TC_HttpResponse(); +// in.setContextData(context, [=]{ delete context; }); +// } + +// if(context->incrementDecode(in)) +// { +// if(context->getStatus() != 200) +// { +// rsp.iRet = taf::JCESERVERUNKNOWNERR; +// rsp.sResultDesc = context->getContent(); +// return TC_NetWorkBuffer::PACKET_FULL; +// } + +// JceInputStream<> is; +// is.setBuffer(context->getContent().c_str() + 4, context->getContent().size() - 4); + +// rsp.readFrom(is); + +// if(!context->checkHeader("Connection", "keep-alive")) +// { +// Transceiver* session = (Transceiver*)(in.getConnection()); + +// session->close(); +// } + +// context = NULL; +// delete context; +// in.setContextData(NULL); + +// return TC_NetWorkBuffer::PACKET_FULL; +// } + +// return TC_NetWorkBuffer::PACKET_LESS; +// } + #if TARS_HTTP2 // ENCODE function, called by network thread @@ -133,10 +205,16 @@ vector ProxyProtocol::http2Request(RequestPacket& request, Transceiver *tr session->settings(3000); } - request.iRequestId = session->submit(request.sFuncName, request.sServantName, request.context, request.sBuffer); + shared_ptr *data = (shared_ptr*)request.sBuffer.data(); + + request.iRequestId = session->submit(*(*data).get()); + + //这里把智能指针释放一次 + (*data).reset(); + if (request.iRequestId < 0) { - TLOGERROR("[TARS]http2Request::Fatal submit error: " << session->getErrMsg() << endl); + TLOGERROR("http2Request::Fatal submit error: " << session->getErrMsg() << endl); return vector(); } @@ -156,8 +234,11 @@ TC_NetWorkBuffer::PACKET_TYPE ProxyProtocol::http2Response(TC_NetWorkBuffer &in, if(flag == TC_NetWorkBuffer::PACKET_FULL) { rsp.iRequestId = out.first; - out.second->getHeaders(rsp.status); - rsp.sBuffer.assign(out.second->getContent().begin(), out.second->getContent().end()); + + rsp.sBuffer.resize(sizeof(shared_ptr)); + + //这里智能指针有一次+1, 后面要自己reset掉 + *(shared_ptr*)rsp.sBuffer.data() = out.second; } return flag; diff --git a/servant/libservant/Application.cpp b/servant/libservant/Application.cpp index c09408bb9ef87884473bee3d20603f4f65f9e244..3fbe41c0996e432a5a0806701287b1b258b45a68 100644 --- a/servant/libservant/Application.cpp +++ b/servant/libservant/Application.cpp @@ -16,7 +16,7 @@ #include "util/tc_option.h" #include "util/tc_common.h" -#include "servant/TarsNodeF.h" +#include "servant/KeepAliveNodeF.h" #include "servant/Application.h" #include "servant/AppProtocol.h" #include "servant/AdminServant.h" @@ -47,11 +47,14 @@ namespace tars #if TARGET_PLATFORM_LINUX || TARGET_PLATFORM_IOS static void sighandler( int sig_no ) { + TLOGERROR("[TARS][sighandler] sig_no :" << sig_no << endl); + Application::terminate(); } #else static BOOL WINAPI HandlerRoutine(DWORD dwCtrlType) { + TLOGERROR("[TARS][sighandler] dwCtrlType :" << dwCtrlType << endl); Application::terminate(); ExitProcess(0); return TRUE; @@ -84,16 +87,18 @@ bool ServerConfig::ManualListen = false; //手工启动监听端口 bool ServerConfig::MergeNetImp = false; //合并网络和处理线程 int ServerConfig::NetThread = 1; //servernet thread bool ServerConfig::CloseCout = true; +int ServerConfig::BackPacketLimit = 0; +int ServerConfig::BackPacketMin = 1024; #if TARS_SSL std::string ServerConfig::CA; std::string ServerConfig::Cert; std::string ServerConfig::Key; bool ServerConfig::VerifyClient = false; +std::string ServerConfig::Ciphers; #endif -#define OUT_LINE (TC_Common::outfill("", '-', 80)) -#define OUT_LINE_LONG (TC_Common::outfill("", '=', 80)) +map ServerConfig::Context; /////////////////////////////////////////////////////////////////////////////////////////// TC_Config Application::_conf; @@ -157,14 +162,12 @@ void reportRspQueue(TC_EpollServer *epollServer) { iLastCheckTime = iNow; - vector vNetThread = epollServer->getNetThread(); - - unsigned int iNetThreadNum = epollServer->getNetThreadNum(); + const vector &adapters = epollServer->getBindAdapters(); size_t n = 0; - for (size_t i = 0; i < iNetThreadNum; ++i) + for (size_t i = 0; i < adapters.size(); ++i) { - n = n + vNetThread[i]->getSendRspSize(); + n = n + adapters[i]->getSendBufferSize(); } g_pReportRspQueue->report((int)n); @@ -196,7 +199,10 @@ void Application::waitForShutdown() destroyApp(); - TarsRemoteNotify::getInstance()->report("stop", true); + RemoteNotify::getInstance()->report("stop"); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); //稍微休息一下, 让当前处理包能够回复 + } void Application::terminate() @@ -297,7 +303,7 @@ bool Application::cmdSetLogLevel(const string& command, const string& params, st string level = TC_Common::trim(params); - int ret = TarsRollLogger::getInstance()->logger()->setLogLevel(level); + int ret = LocalRollLogger::getInstance()->logger()->setLogLevel(level); if(ret == 0) { @@ -367,13 +373,13 @@ bool Application::cmdEnableDayLog(const string& command, const string& params, s if(vParams[0] == "local") { - TarsTimeLogger::getInstance()->enableLocal(sFile,bEnable); + RemoteTimeLogger::getInstance()->enableLocal(sFile,bEnable); return true; } if(vParams[0] == "remote") { - TarsTimeLogger::getInstance()->enableRemote(sFile,bEnable); + RemoteTimeLogger::getInstance()->enableRemote(sFile,bEnable); return true; } @@ -388,14 +394,14 @@ bool Application::cmdLoadConfig(const string& command, const string& params, str string filename = TC_Common::trim(params); - if (TarsRemoteConfig::getInstance()->addConfig(filename, result,false)) + if (RemoteConfig::getInstance()->addConfig(filename, result,false)) { - TarsRemoteNotify::getInstance()->report(result); + RemoteNotify::getInstance()->report(result); return true; } - TarsRemoteNotify::getInstance()->report(result); + RemoteNotify::getInstance()->report(result); return true; } @@ -419,14 +425,20 @@ bool Application::cmdConnections(const string& command, const string& params, st os << TC_Common::outfill("conn-uid", ' ', 15) << TC_Common::outfill("ip:port", ' ', 25) << TC_Common::outfill("last-time", ' ', 25) - << TC_Common::outfill("timeout", ' ', 10) << endl; + << TC_Common::outfill("timeout", ' ', 10) + << TC_Common::outfill("recvBufferSize", ' ', 30) + << TC_Common::outfill("sendBufferSize", ' ', 30) + << endl; for (size_t i = 0; i < v.size(); i++) { os << TC_Common::outfill(TC_Common::tostr(v[i].uid), ' ', 15) << TC_Common::outfill(v[i].ip + ":" + TC_Common::tostr(v[i].port), ' ', 25) << TC_Common::outfill(TC_Common::tm2str(v[i].iLastRefreshTime, "%Y-%m-%d %H:%M:%S"), ' ', 25) - << TC_Common::outfill(TC_Common::tostr(v[i].timeout), ' ', 10) << endl; + << TC_Common::outfill(TC_Common::tostr(v[i].timeout), ' ', 10) + << TC_Common::outfill(TC_Common::tostr(v[i].recvBufferSize), ' ', 30) + << TC_Common::outfill(TC_Common::tostr(v[i].sendBufferSize), ' ', 30) + << endl; } } os << OUT_LINE_LONG << endl; @@ -442,6 +454,33 @@ bool Application::cmdViewVersion(const string& command, const string& params, st return true; } +bool Application::cmdViewBuildID(const string& command, const string& params, string& result) +{ + #define YEARSUF ((__DATE__ [9] - '0') * 10 + (__DATE__ [10] - '0')) + + #define MONTH (__DATE__ [2] == 'n' ? (__DATE__ [1] == 'a' ? 0 : 5) \ + : __DATE__ [2] == 'b' ? 1 \ + : __DATE__ [2] == 'r' ? (__DATE__ [0] == 'M' ? 2 : 3) \ + : __DATE__ [2] == 'y' ? 4 \ + : __DATE__ [2] == 'l' ? 6 \ + : __DATE__ [2] == 'g' ? 7 \ + : __DATE__ [2] == 'p' ? 8 \ + : __DATE__ [2] == 't' ? 9 \ + : __DATE__ [2] == 'v' ? 10 : 11) + + #define DAY ((__DATE__ [4] == ' ' ? 0 : __DATE__ [4] - '0') * 10 \ + + (__DATE__ [5] - '0')) + + #define TIMEINT ((((((__TIME__[0] - '0') * 10 + (__TIME__[1] - '0')) * 10 \ + + (__TIME__[3] - '0')) * 10 + (__TIME__[4] - '0')) * 10 \ + + (__TIME__[6] - '0')) * 10 + (__TIME__[7] - '0')) + + char buildTime[50] = {0}; + sprintf(buildTime, "%d.%02d%02d.%06d", YEARSUF, MONTH + 1, DAY, TIMEINT); + result = "$" + ServerConfig::Application + "." + ServerConfig::ServerName + "-" + string(buildTime) + "$"; + return true; +} + bool Application::cmdLoadProperty(const string& command, const string& params, string& result) { try @@ -461,15 +500,15 @@ bool Application::cmdLoadProperty(const string& command, const string& params, s //加载远程对象 ServerConfig::Log = _conf.get("/tars/application/server"); - TarsTimeLogger::getInstance()->setLogInfo(_communicator, ServerConfig::Log, ServerConfig::Application, ServerConfig::ServerName, ServerConfig::LogPath,setDivision()); + RemoteTimeLogger::getInstance()->setLogInfo(_communicator, ServerConfig::Log, ServerConfig::Application, ServerConfig::ServerName, ServerConfig::LogPath,setDivision()); ServerConfig::Config = _conf.get("/tars/application/server"); - TarsRemoteConfig::getInstance()->setConfigInfo(_communicator, ServerConfig::Config, ServerConfig::Application, ServerConfig::ServerName, ServerConfig::BasePath,setDivision()); + RemoteConfig::getInstance()->setConfigInfo(_communicator, ServerConfig::Config, ServerConfig::Application, ServerConfig::ServerName, ServerConfig::BasePath,setDivision(), 5); ServerConfig::Notify = _conf.get("/tars/application/server"); - TarsRemoteNotify::getInstance()->setNotifyInfo(_communicator, ServerConfig::Notify, ServerConfig::Application, ServerConfig::ServerName, ServerConfig::LocalIp, setDivision()); + RemoteNotify::getInstance()->setNotifyInfo(_communicator, ServerConfig::Notify, ServerConfig::Application, ServerConfig::ServerName, setDivision(), ServerConfig::LocalIp); result = "loaded config items:\r\n" + sResult + "log=" + ServerConfig::Log + "\r\n" + @@ -574,6 +613,31 @@ bool Application::cmdReloadLocator(const string& command, const string& params, return bSucc; } +bool Application::cmdViewResource(const string& command, const string& params, string& result) +{ + TLOGDEBUG("Application::cmdViewResource:" << command << " " << params << endl); + + ostringstream os; + + os << _communicator->getResourcesInfo() << endl; + + os << OUT_LINE << endl; + + vector adapters = _epollServer->getBindAdapters(); + for(auto adapter : adapters) + { + outAdapter(os, ServantHelperManager::getInstance()->getAdapterServant(adapter->getName()), adapter); + os << TC_Common::outfill("recv-buffer-count") << adapter->getRecvBufferSize() << endl; + os << TC_Common::outfill("send-buffer-count") << adapter->getSendBufferSize() << endl; + } + + result += os.str(); + + TLOGDEBUG("Application::cmdViewResource result:" << result << endl); + + return true; +} + void Application::outAllAdapter(ostream &os) { auto m = _epollServer->getListenSocketInfo(); @@ -590,13 +654,13 @@ bool Application::addConfig(const string &filename) { string result; - if (TarsRemoteConfig::getInstance()->addConfig(filename, result, false)) + if (RemoteConfig::getInstance()->addConfig(filename, result, false)) { - TarsRemoteNotify::getInstance()->report(result); + RemoteNotify::getInstance()->report(result); return true; } - TarsRemoteNotify::getInstance()->report(result); + RemoteNotify::getInstance()->report(result); return true; } @@ -606,15 +670,15 @@ bool Application::addAppConfig(const string &filename) string result = ""; // true-只获取应用级别配置 - if (TarsRemoteConfig::getInstance()->addConfig(filename, result, true)) + if (RemoteConfig::getInstance()->addConfig(filename, result, true)) { - TarsRemoteNotify::getInstance()->report(result); + RemoteNotify::getInstance()->report(result); return true; } - TarsRemoteNotify::getInstance()->report(result); + RemoteNotify::getInstance()->report(result); return true; } @@ -667,7 +731,7 @@ void Application::main(const TC_Option &option) //等待initialize初始化完毕 std::unique_lock lock(mtx); - cond.wait_for(lock, std::chrono::seconds(5)); + cond.wait_for(lock, std::chrono::seconds(2)); }while(initing); }); @@ -687,8 +751,10 @@ void Application::main(const TC_Option &option) catch (exception & ex) { keepActiving.detach(); - TarsRemoteNotify::getInstance()->report("exit: " + string(ex.what())); - cout << "[init exception]:" << ex.what() << endl; + RemoteNotify::getInstance()->report("exit: " + string(ex.what())); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); //稍微休息一下, 让当前处理包能够回复 + + cout << "[init exception]:" << ex.what() << endl; exit(-1); } } @@ -711,6 +777,9 @@ void Application::main(const TC_Option &option) //查看编译的TARS版本 TARS_ADD_ADMIN_CMD_PREFIX(TARS_CMD_VIEW_VERSION, Application::cmdViewVersion); + //查看服务buildid(编译时间) + TARS_ADD_ADMIN_CMD_PREFIX(TARS_CMD_VIEW_BID, Application::cmdViewBuildID); + //加载配置文件中的属性信息 TARS_ADD_ADMIN_CMD_PREFIX(TARS_CMD_LOAD_PROPERTY, Application::cmdLoadProperty); @@ -726,6 +795,12 @@ void Application::main(const TC_Option &option) //设置是否标准输出 TARS_ADD_ADMIN_CMD_PREFIX(TARS_CMD_CLOSE_COUT, Application::cmdCloseCout); + //设置是否标准输出 + TARS_ADD_ADMIN_CMD_PREFIX(TARS_CMD_RELOAD_LOCATOR, Application::cmdReloadLocator); + + //设置是否标准输出 + TARS_ADD_ADMIN_CMD_PREFIX(TARS_CMD_RESOURCE, Application::cmdViewResource); + //上报版本 TARS_REPORTVERSION(TARS_VERSION); @@ -733,7 +808,7 @@ void Application::main(const TC_Option &option) TARS_KEEPALIVE(""); //发送给notify表示服务启动了 - TarsRemoteNotify::getInstance()->report("restart"); + RemoteNotify::getInstance()->report("restart"); //ctrl + c能够完美结束服务 #if TARGET_PLATFORM_LINUX || TARGET_PLATFORM_IOS @@ -767,13 +842,15 @@ void Application::main(const TC_Option &option) { cout << "[main exception]:" << ex.what() << endl; - TarsRemoteNotify::getInstance()->report("exit: " + string(ex.what())); - - exit(-1); + RemoteNotify::getInstance()->report("exit: " + string(ex.what())); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); //稍微休息一下, 让当前处理包能够回复 + + exit(-1); } //初始化完毕后, 日志再修改为异步 - TarsRollLogger::getInstance()->sync(false); + LocalRollLogger::getInstance()->sync(false); } void Application::parseConfig(const TC_Option &op) @@ -850,7 +927,7 @@ void Application::outClient(ostream &os) os << TC_Common::outfill("property") << _communicator->getProperty("property") << endl; os << TC_Common::outfill("report-interval") << _communicator->getProperty("report-interval") << endl; // os << TC_Common::outfill("sample-rate") << _communicator->getProperty("sample-rate") << endl; - os << TC_Common::outfill("max-sample-count") << _communicator->getProperty("max-sample-count") << endl; +// os << TC_Common::outfill("max-sample-count") << _communicator->getProperty("max-sample-count") << endl; os << TC_Common::outfill("netthread") << _communicator->getProperty("netthread") << endl; os << TC_Common::outfill("asyncthread") << _communicator->getProperty("asyncthread") << endl; os << TC_Common::outfill("modulename") << _communicator->getProperty("modulename") << endl; @@ -921,12 +998,16 @@ void Application::outServer(ostream &os) os << TC_Common::outfill("NetThread(netthread)") << ServerConfig::NetThread << endl; os << TC_Common::outfill("ManualListen(manuallisten)") << ServerConfig::ManualListen << endl; os << TC_Common::outfill("MergeNetImp(mergenetimp)") << ServerConfig::MergeNetImp << endl; - os << TC_Common::outfill("ReportFlow") << ServerConfig::ReportFlow<< endl; + os << TC_Common::outfill("ReportFlow(reportflow)") << ServerConfig::ReportFlow<< endl; + os << TC_Common::outfill("BackPacketLimit(backpacketlimit)") << ServerConfig::BackPacketLimit<< endl; + os << TC_Common::outfill("BackPacketMin(backpacketmin)") << ServerConfig::BackPacketMin<< endl; + #if TARS_SSL - cout << TC_Common::outfill("Ca") << ServerConfig::CA << endl; - cout << TC_Common::outfill("Cert") << ServerConfig::Cert << endl; - cout << TC_Common::outfill("Key") << ServerConfig::Key << endl; - cout << TC_Common::outfill("VerifyClient") << ServerConfig::VerifyClient << endl; + cout << TC_Common::outfill("Ca(ca)") << ServerConfig::CA << endl; + cout << TC_Common::outfill("Cert(cert)") << ServerConfig::Cert << endl; + cout << TC_Common::outfill("Key(key)") << ServerConfig::Key << endl; + cout << TC_Common::outfill("VerifyClient(verifyclient)") << ServerConfig::VerifyClient << endl; + cout << TC_Common::outfill("Ciphers(ciphers)") << ServerConfig::Ciphers << endl; #endif } @@ -991,21 +1072,25 @@ void Application::initializeServer() ServerConfig::ReportFlow = _conf.get("/tars/application/server")=="0"?0:1; ServerConfig::IsCheckSet = _conf.get("/tars/application/server","1")=="0"?0:1; ServerConfig::OpenCoroutine = TC_Common::strto(toDefault(_conf.get("/tars/application/server"), "0")); - ServerConfig::CoroutineMemSize = TC_Common::toSize(toDefault(_conf.get("/tars/application/server"), "1073741824"), 1073741824); - ServerConfig::CoroutineStackSize= (uint32_t)TC_Common::toSize(toDefault(_conf.get("/tars/application/server"), "131072"), 131072); + ServerConfig::CoroutineMemSize = TC_Common::toSize(toDefault(_conf.get("/tars/application/server"), "1G"), 1024*1024*1024); + ServerConfig::CoroutineStackSize= (uint32_t)TC_Common::toSize(toDefault(_conf.get("/tars/application/server"), "128K"), 1024*128); ServerConfig::ManualListen = _conf.get("/tars/application/server", "0") == "0" ? false : true; ServerConfig::MergeNetImp = _conf.get("/tars/application/server", "0") == "0" ? false : true; - ServerConfig::NetThread = TC_Common::strto(toDefault(_conf.get("/tars/application/server"), "1")); + ServerConfig::NetThread = TC_Common::strto(toDefault(_conf.get("/tars/application/server"), "1")); ServerConfig::CloseCout = _conf.get("/tars/application/server","1")=="0"?0:1; + ServerConfig::BackPacketLimit = TC_Common::strto(_conf.get("/tars/application/server", "100*1024*1024")); + ServerConfig::BackPacketMin = TC_Common::strto(_conf.get("/tars/application/server", "1024")); + ServerConfig::Context["node_name"] = ServerConfig::LocalIp; #if TARS_SSL ServerConfig::CA = _conf.get("/tars/application/server"); ServerConfig::Cert = _conf.get("/tars/application/server"); ServerConfig::Key = _conf.get("/tars/application/server"); ServerConfig::VerifyClient = _conf.get("/tars/application/server","0")=="0"?false:true; + ServerConfig::Ciphers = _conf.get("/tars/application/server"); if(!ServerConfig::Cert.empty()) { - _ctx = TC_OpenSSL::newCtx(ServerConfig::CA, ServerConfig::Cert, ServerConfig::Key, ServerConfig::VerifyClient); + _ctx = TC_OpenSSL::newCtx(ServerConfig::CA, ServerConfig::Cert, ServerConfig::Key, ServerConfig::VerifyClient, ServerConfig::Ciphers); if (!_ctx) { TLOGERROR("[TARS]load server ssl error, ca:" << ServerConfig::CA << endl); @@ -1067,11 +1152,11 @@ void Application::initializeServer() /////////////////////////////////////////////////////////////////////////////////////////////////// //初始化本地Log cout << OUT_LINE << "\n" << TC_Common::outfill("[set roll logger] ") << "OK" << endl; - TarsRollLogger::getInstance()->setLogInfo(ServerConfig::Application, ServerConfig::ServerName, ServerConfig::LogPath, ServerConfig::LogSize, ServerConfig::LogNum, _communicator, ServerConfig::Log); - _epollServer->setLocalLogger(TarsRollLogger::getInstance()->logger()); + LocalRollLogger::getInstance()->setLogInfo(ServerConfig::Application, ServerConfig::ServerName, ServerConfig::LogPath, ServerConfig::LogSize, ServerConfig::LogNum, _communicator, ServerConfig::Log); + _epollServer->setLocalLogger(LocalRollLogger::getInstance()->logger()); //初始化是日志为同步 - TarsRollLogger::getInstance()->sync(true); + LocalRollLogger::getInstance()->sync(true); //设置日志级别 string level = AppCache::getInstance()->get("logLevel"); @@ -1082,28 +1167,28 @@ void Application::initializeServer() ServerConfig::LogLevel = TC_Common::upper(level); - TarsRollLogger::getInstance()->logger()->setLogLevel(ServerConfig::LogLevel); + LocalRollLogger::getInstance()->logger()->setLogLevel(ServerConfig::LogLevel); /////////////////////////////////////////////////////////////////////////////////////////////////// //初始化到LogServer代理 cout << OUT_LINE << "\n" << TC_Common::outfill("[set time logger] ") << "OK" << endl; bool bLogStatReport = (_conf.get("/tars/application/server", "0") == "1") ? true : false; - TarsTimeLogger::getInstance()->setLogInfo(_communicator, ServerConfig::Log, ServerConfig::Application, ServerConfig::ServerName, ServerConfig::LogPath, setDivision(), bLogStatReport); + RemoteTimeLogger::getInstance()->setLogInfo(_communicator, ServerConfig::Log, ServerConfig::Application, ServerConfig::ServerName, ServerConfig::LogPath, setDivision(), bLogStatReport); /////////////////////////////////////////////////////////////////////////////////////////////////// //初始化到配置中心代理 cout << OUT_LINE << "\n" << TC_Common::outfill("[set remote config] ") << "OK" << endl; - TarsRemoteConfig::getInstance()->setConfigInfo(_communicator, ServerConfig::Config, ServerConfig::Application, ServerConfig::ServerName, ServerConfig::BasePath,setDivision()); + RemoteConfig::getInstance()->setConfigInfo(_communicator, ServerConfig::Config, ServerConfig::Application, ServerConfig::ServerName, ServerConfig::BasePath,setDivision()); /////////////////////////////////////////////////////////////////////////////////////////////////// //初始化到信息中心代理 cout << OUT_LINE << "\n" << TC_Common::outfill("[set remote notify] ") << "OK" << endl; - TarsRemoteNotify::getInstance()->setNotifyInfo(_communicator, ServerConfig::Notify, ServerConfig::Application, ServerConfig::ServerName, setDivision()); + RemoteNotify::getInstance()->setNotifyInfo(_communicator, ServerConfig::Notify, ServerConfig::Application, ServerConfig::ServerName, setDivision(), ServerConfig::LocalIp); /////////////////////////////////////////////////////////////////////////////////////////////////// //初始化到Node的代理 cout << OUT_LINE << "\n" << TC_Common::outfill("[set node proxy]") << "OK" << endl; - TarsNodeFHelper::getInstance()->setNodeInfo(_communicator, ServerConfig::Node, ServerConfig::Application, ServerConfig::ServerName); + KeepAliveNodeFHelper::getInstance()->setNodeInfo(_communicator, ServerConfig::Node, ServerConfig::Application, ServerConfig::ServerName); /////////////////////////////////////////////////////////////////////////////////////////////////// //初始化管理对象 @@ -1174,11 +1259,12 @@ void Application::setAdapter(TC_EpollServer::BindAdapterPtr& adapter, const stri string key = _conf.get("/tars/application/server/" + name + ""); bool verifyClient = _conf.get("/tars/application/server/" + name + "", "0") == "0" ? false : true; + string ciphers = _conf.get("/tars/application/server/" + name + ""); - shared_ptr ctx = TC_OpenSSL::newCtx(ca, cert, key, verifyClient); + shared_ptr ctx = TC_OpenSSL::newCtx(ca, cert, key, verifyClient, ciphers); if (!ctx) { - TLOGERROR("[TARS]load server ssl error, cert:" << cert << endl); + TLOGERROR("load server ssl error, cert:" << cert << endl); exit(-1); } @@ -1243,7 +1329,10 @@ void Application::bindAdapter(vector& adapters) bindAdapter->setProtocolName(_conf.get(sLastPath + "", "tars")); - if (bindAdapter->isTarsProtocol()) + bindAdapter->setBackPacketBuffLimit(ServerConfig::BackPacketLimit); + bindAdapter->setBackPacketBuffMin(ServerConfig::BackPacketMin); + + if (bindAdapter->isTarsProtocol()) { bindAdapter->setProtocol(AppProtocol::parse); } @@ -1284,10 +1373,11 @@ void Application::checkServantNameValid(const string& servant, const string& sPr os << "Servant '" << servant << "' error: must be start with '" << sPrefix << "'"; - TarsRemoteNotify::getInstance()->report("exit:" + os.str()); + RemoteNotify::getInstance()->report("exit:" + os.str()); - cout << os.str() << endl; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); //稍微休息一下, 让当前处理包能够回复 + cout << os.str() << endl; exit(-1); } diff --git a/servant/libservant/AsyncProcThread.cpp b/servant/libservant/AsyncProcThread.cpp index c64781c3b96b607056b7ba67c5b349c2f6b56f3e..588e1eb84cc5b16296b71b0929060ff6cc52889f 100644 --- a/servant/libservant/AsyncProcThread.cpp +++ b/servant/libservant/AsyncProcThread.cpp @@ -17,7 +17,7 @@ #include "servant/AsyncProcThread.h" #include "servant/Communicator.h" #include "servant/StatReport.h" -#include "servant/TarsLogger.h" +#include "servant/RemoteLogger.h" namespace tars { @@ -64,7 +64,7 @@ void AsyncProcThread::push_back(ReqMessage * msg) else { if(_msgQueue->size() >= _iQueueCap) { - TLOGERROR("[TARS][AsyncProcThread::push_back] async_queue full:" << _msgQueue->size() << ">=" << _iQueueCap << endl); + TLOGERROR("[AsyncProcThread::push_back] async_queue full:" << _msgQueue->size() << ">=" << _iQueueCap << endl); delete msg; } else @@ -109,6 +109,8 @@ void AsyncProcThread::callback(ReqMessage * msg) pServantProxyThreadData->_dyeing = msg->bDyeing; pServantProxyThreadData->_dyeingKey = msg->sDyeingKey; + pServantProxyThreadData->_cookie = msg->cookie; + if(msg->adapter) { pServantProxyThreadData->_szHost = msg->adapter->endpoint().desc(); @@ -117,7 +119,7 @@ void AsyncProcThread::callback(ReqMessage * msg) try { ReqMessagePtr msgPtr = msg; - msg->callback->onDispatch(msgPtr); + msg->callback->dispatch(msgPtr); } catch (exception& e) { diff --git a/servant/libservant/AuthLogic.cpp b/servant/libservant/AuthLogic.cpp index fb1d3000865a7981acd9175817f1b3541c6daa89..9907cda10f86015d8b40dff77b5e3a8bf4ae86e6 100644 --- a/servant/libservant/AuthLogic.cpp +++ b/servant/libservant/AuthLogic.cpp @@ -39,7 +39,7 @@ bool processAuth(TC_EpollServer::Connection *conn, const shared_ptrgetEndpoint().getAuthType(); if (type == AUTH_TYPENONE) { - adapter->getEpollServer()->info("[TARS]processAuth no need auth func, auth succ"); + adapter->getEpollServer()->info("processAuth no need auth func, auth succ"); conn->_authState = AUTH_SUCC; return false; } @@ -59,7 +59,7 @@ bool processAuth(TC_EpollServer::Connection *conn, const shared_ptrgetEpollServer()->error("[TARS]processAuth tars protocol decode error, close connection."); + adapter->getEpollServer()->error("processAuth tars protocol decode error, close connection."); conn->setClose(); return true; diff --git a/servant/libservant/CMakeLists.txt b/servant/libservant/CMakeLists.txt index 1048675a89f2590d725ed8a625f78f340e0ea635..3ab667fb0da951d6131cbd9997d2bbea298b1f0e 100755 --- a/servant/libservant/CMakeLists.txt +++ b/servant/libservant/CMakeLists.txt @@ -1,4 +1,4 @@ -if(_USE_OPENTRACKING) +if(TARS_OPENTRACKING) include_directories(${PROJECT_SOURCE_DIR} ${OPENTRACKING_INC}) else() include_directories(${PROJECT_SOURCE_DIR}) diff --git a/servant/libservant/Communicator.cpp b/servant/libservant/Communicator.cpp index 7744a49aa28869d9506264744ffe08345101a50d..f0d26644cd1348e8a68050a30e45eb6b2b00a8e3 100644 --- a/servant/libservant/Communicator.cpp +++ b/servant/libservant/Communicator.cpp @@ -15,10 +15,10 @@ */ #include "util/tc_file.h" - #include "servant/Communicator.h" +#include "servant/Application.h" #include "servant/StatReport.h" -#include "servant/TarsLogger.h" +#include "servant/RemoteLogger.h" namespace tars { @@ -46,7 +46,7 @@ Communicator::Communicator() , _statReport(NULL) , _timeoutLogFlag(true) , _minTimeout(100) -#ifdef _USE_OPENTRACKING +#ifdef TARS_OPENTRACKING , _traceManager(NULL) #endif { @@ -61,7 +61,7 @@ Communicator::Communicator(TC_Config& conf, const string& domain/* = CONFIG_ROOT : _initialized(false) , _terminating(false) , _timeoutLogFlag(true) -#ifdef _USE_OPENTRACKING +#ifdef TARS_OPENTRACKING , _traceManager(NULL) #endif { @@ -120,6 +120,13 @@ string Communicator::getServantProperty(const string &sObj, const string& name) return ""; } +void Communicator::setServantCustomCallback(const string &sObj, Communicator::custom_callback callback) +{ + TC_LockT lock(_callbackLock); + + _callback[sObj] = callback; +} + #if TARS_SSL shared_ptr Communicator::newClientSSL(const string & objName) { @@ -131,6 +138,10 @@ shared_ptr Communicator::newClientSSL(const string & objName) return TC_OpenSSL::newSSL(it->second); } + if(!_ctx) { + _ctx = TC_OpenSSL::newCtx("", "", "", false, ""); + } + return TC_OpenSSL::newSSL(_ctx); } @@ -161,14 +172,16 @@ void Communicator::setProperty(TC_Config& conf, const string& domain/* = CONFIG_ data["ca"] = conf.get("/tars/application/client/" + auths[i] + ""); data["cert"] = conf.get("/tars/application/client/" + auths[i] + ""); data["key"] = conf.get("/tars/application/client/" + auths[i] + ""); + data["ciphers"] = conf.get("/tars/application/client/" + auths[i] + ""); + #if TARS_SSL if(!data["ca"].empty()) { - shared_ptr ctx = TC_OpenSSL::newCtx( data["ca"], data["cert"], data["key"], false); + shared_ptr ctx = TC_OpenSSL::newCtx( data["ca"], data["cert"], data["key"], false, data["ciphers"]); if(!ctx) { - TLOGERROR("[TARS]load obj:" << auths[i] << ", ssl error, ca:" << data["ca"] << endl); + TLOGERROR("load obj:" << auths[i] << ", ssl error, ca:" << data["ca"] << endl); exit(-1); } @@ -206,7 +219,7 @@ void Communicator::initialize() //set分组名不对时默认没有打开set分组 ClientConfig::SetOpen = false; setProperty("enableset","n"); - TLOGERROR( "[TARS][set division name error:" << ClientConfig::SetDivision << ", client failed to open set]" << endl); + TLOGERROR( "[set division name error:" << ClientConfig::SetDivision << ", client failed to open set]" << endl); } } @@ -244,13 +257,14 @@ void Communicator::initialize() string ca = getProperty("ca"); string cert = getProperty("cert"); string key = getProperty("key"); + string ciphers = getProperty("ciphers"); if(!ca.empty()) { - _ctx = TC_OpenSSL::newCtx(ca, cert, key, false); + _ctx = TC_OpenSSL::newCtx(ca, cert, key, false, ciphers); if(!_ctx) { - TLOGERROR("[TARS]load client ssl error, ca:" << ca << endl); + TLOGERROR("load client ssl error, ca:" << ca << endl); exit(-1); } } @@ -317,9 +331,9 @@ void Communicator::initialize() int iReportTimeout = TC_Common::strto(getProperty("report-timeout", "5000")); - int iSampleRate = TC_Common::strto(getProperty("sample-rate", "1000")); + // int iSampleRate = TC_Common::strto(getProperty("sample-rate", "1000")); - int iMaxSampleCount = TC_Common::strto(getProperty("max-sample-count", "100")); + // int iMaxSampleCount = TC_Common::strto(getProperty("max-sample-count", "100")); int iMaxReportSize = TC_Common::strto(getProperty("max-report-size", "1400")); @@ -343,9 +357,9 @@ void Communicator::initialize() } string sSetDivision = ClientConfig::SetOpen?ClientConfig::SetDivision:""; - _statReport->setReportInfo(statPrx, propertyPrx, ClientConfig::ModuleName, ClientConfig::LocalIp, sSetDivision, iReportInterval, iSampleRate, iMaxSampleCount, iMaxReportSize, iReportTimeout); + _statReport->setReportInfo(statPrx, propertyPrx, ClientConfig::ModuleName, ClientConfig::LocalIp, sSetDivision, iReportInterval, 0, 0, iMaxReportSize, iReportTimeout); -#if _USE_OPENTRACKING +#if TARS_OPENTRACKING string collector_host = getProperty("collector_host", ""); string collector_port = getProperty("collector_port", ""); if(!collector_host.empty() && !collector_port.empty()) @@ -412,9 +426,9 @@ int Communicator::reloadProperty(string & sResult) int iReportTimeout = TC_Common::strto(getProperty("report-timeout", "5000")); - int iSampleRate = TC_Common::strto(getProperty("sample-rate", "1000")); + // int iSampleRate = TC_Common::strto(getProperty("sample-rate", "1000")); - int iMaxSampleCount = TC_Common::strto(getProperty("max-sample-count", "100")); + // int iMaxSampleCount = TC_Common::strto(getProperty("max-sample-count", "100")); int iMaxReportSize = TC_Common::strto(getProperty("max-report-size", "1400")); @@ -437,15 +451,15 @@ int Communicator::reloadProperty(string & sResult) } string sSetDivision = ClientConfig::SetOpen?ClientConfig::SetDivision:""; - _statReport->setReportInfo(statPrx, propertyPrx, ClientConfig::ModuleName, ClientConfig::LocalIp, sSetDivision, iReportInterval, iSampleRate, iMaxSampleCount, iMaxReportSize, iReportTimeout); + _statReport->setReportInfo(statPrx, propertyPrx, ClientConfig::ModuleName, ClientConfig::LocalIp, sSetDivision, iReportInterval, 0, 0, iMaxReportSize, iReportTimeout); sResult = "locator=" + getProperty("locator", "") + "\r\n" + "stat=" + statObj + "\r\n" + "property=" + propertyObj + "\r\n" + "SetDivision=" + sSetDivision + "\r\n" + "report-interval=" + TC_Common::tostr(iReportInterval) + "\r\n" + - "report-timeout=" + TC_Common::tostr(iReportTimeout) + "\r\n" + - "sample-rate=" + TC_Common::tostr(iSampleRate) + "\r\n" + - "max-sample-count=" + TC_Common::tostr(iMaxSampleCount) + "\r\n"; + "report-timeout=" + TC_Common::tostr(iReportTimeout) + "\r\n"; + // "sample-rate=" + TC_Common::tostr(iSampleRate) + "\r\n" + + // "max-sample-count=" + TC_Common::tostr(iMaxSampleCount) + "\r\n"; return 0; } @@ -458,10 +472,21 @@ vector Communicator::getEndpoint(const string & objName) vector Communicator::getEndpoint4All(const string & objName) { - ServantProxy * pServantProxy = getServantProxy(objName); + ServantProxy *pServantProxy = getServantProxy(objName); return pServantProxy->getEndpoint4All(); } +string Communicator::getResourcesInfo() +{ + ostringstream os; + for (size_t i = 0; i < _clientThreadNum; ++i) + { + os << OUT_LINE << endl; + os << _communicatorEpoll[i]->getResourcesInfo(); + } + return os.str(); +} + void Communicator::terminate() { { @@ -531,8 +556,19 @@ void Communicator::terminate() void Communicator::pushAsyncThreadQueue(ReqMessage * msg) { - //先不考虑每个线程队列数目不一致的情况 - _asyncThread[(_asyncSeq++)%_asyncThreadNum]->push_back(msg); + { + TC_LockT lock(_callbackLock); + + auto it = _callback.find(msg->request.sServantName); + if (it != _callback.end()) { + ReqMessagePtr msgPtr = msg; + it->second(msgPtr); + return; + } + } + + //先不考虑每个线程队列数目不一致的情况 + _asyncThread[(_asyncSeq++) % _asyncThreadNum]->push_back(msg); } void Communicator::doStat() diff --git a/servant/libservant/CommunicatorEpoll.cpp b/servant/libservant/CommunicatorEpoll.cpp index 35057d165baca967627c6be6f450eef8006299c3..4c7412157b57c091eb168a2e83e2e05a3283c54c 100755 --- a/servant/libservant/CommunicatorEpoll.cpp +++ b/servant/libservant/CommunicatorEpoll.cpp @@ -16,7 +16,8 @@ #include "servant/CommunicatorEpoll.h" #include "servant/Communicator.h" -#include "servant/TarsLogger.h" +#include "servant/Application.h" +#include "servant/RemoteLogger.h" #include "servant/StatReport.h" using namespace std; @@ -148,7 +149,7 @@ void CommunicatorEpoll::handleInputImp(Transceiver * pTransceiver) { pTransceiver->close(); pTransceiver->getAdapterProxy()->addConnExc(true); - TLOGERROR("[TARS][CommunicatorEpoll::handleInputImp] connect error " + TLOGERROR("[CommunicatorEpoll::handleInputImp] connect error " << pTransceiver->getAdapterProxy()->endpoint().desc() << "," << pTransceiver->getAdapterProxy()->getObjProxy()->name() << ",_connExcCnt=" << pTransceiver->getAdapterProxy()->ConnExcCnt() @@ -173,7 +174,7 @@ void CommunicatorEpoll::handleOutputImp(Transceiver * pTransceiver) { pTransceiver->close(); pTransceiver->getAdapterProxy()->addConnExc(true); - TLOGERROR("[TARS][CommunicatorEpoll::handleOutputImp] connect error " + TLOGERROR("[CommunicatorEpoll::handleOutputImp] connect error " << pTransceiver->getAdapterProxy()->endpoint().desc() << "," << pTransceiver->getAdapterProxy()->getObjProxy()->name() << ",_connExcCnt=" << pTransceiver->getAdapterProxy()->ConnExcCnt() @@ -239,11 +240,11 @@ void CommunicatorEpoll::handle(FDInfo * pFDInfo, const epoll_event &ev) } catch(exception & e) { - TLOGERROR("[TARS]CommunicatorEpoll::handle exp:"< 1000) @@ -256,11 +257,11 @@ void CommunicatorEpoll::handle(FDInfo * pFDInfo, const epoll_event &ev) } catch(exception & e) { - TLOGERROR("[TARS]CommunicatorEpoll::handle exp:"<pushAsyncThreadQueue(msg); +} + +void CommunicatorEpoll::reConnect(int64_t ms, Transceiver*p) +{ + _reconnect[ms] = p; +} + +string CommunicatorEpoll::getResourcesInfo() +{ + ostringstream desc; + desc << TC_Common::outfill("index") << _netThreadSeq << endl; + if(_communicator->_statReport) { + desc << TC_Common::outfill("stat size") << _communicator->_statReport->getQueueSize(_netThreadSeq) << endl; + } + desc << TC_Common::outfill("obj num") << _objectProxyFactory->getObjNum() << endl; + + const static string TAB = " "; + for(size_t i = 0; i < _objectProxyFactory->getObjNum(); ++i) + { + desc << TAB << OUT_LINE_TAB(1) << endl; + + desc << TAB << TC_Common::outfill("obj name") << _objectProxyFactory->getObjectProxy(i)->name() << endl; + const vector &adapters = _objectProxyFactory->getObjectProxy(i)->getAdapters(); + + for(auto adapter : adapters) + { + desc << TAB << TAB << OUT_LINE_TAB(2) << endl; + desc << TAB << TAB << TC_Common::outfill("adapter") << adapter->endpoint().getEndpoint().toString() << endl; + desc << TAB << TAB << TC_Common::outfill("recv size") << adapter->trans()->getRecvBuffer()->getBufferLength() << endl; + desc << TAB << TAB << TC_Common::outfill("send size") << adapter->trans()->getSendBuffer()->getBufferLength() << endl; + } + } + + return desc.str(); +} + +void CommunicatorEpoll::reConnect() +{ + int64_t iNow = TNOWMS; + + while(!_reconnect.empty()) + { + auto it = _reconnect.begin(); + + if(it->first > iNow) + { + return; + } + + it->second->reconnect(); + + _reconnect.erase(it++); + } } void CommunicatorEpoll::run() @@ -419,14 +473,15 @@ void CommunicatorEpoll::run() //数据上报 doStat(); + reConnect(); } catch (exception& e) { - TLOGERROR("[TARS][CommunicatorEpoll:run exception:" << e.what() << "]" << endl); + TLOGERROR("[CommunicatorEpoll:run exception:" << e.what() << "]" << endl); } catch (...) { - TLOGERROR("[TARS][CommunicatorEpoll:run exception.]" << endl); + TLOGERROR("[CommunicatorEpoll:run exception.]" << endl); } } } diff --git a/servant/libservant/CoroutineScheduler.cpp b/servant/libservant/CoroutineScheduler.cpp index 633d90c26384da58f91ffb4379e56b2f905091cc..ed214265a22e50256df6f8483a5408b6aaa78516 100644 --- a/servant/libservant/CoroutineScheduler.cpp +++ b/servant/libservant/CoroutineScheduler.cpp @@ -33,7 +33,7 @@ #include #include "util/tc_timeprovider.h" -#include "servant/TarsLogger.h" +#include "servant/RemoteLogger.h" #include "servant/ServantHandle.h" namespace tars @@ -289,11 +289,11 @@ void CoroutineInfo::corotineEntry(transfer_t tf) } catch(std::exception &ex) { - TLOGERROR("[TARS][CoroutineInfo::corotineEntry exception:" << ex.what() << endl); + TLOGERROR("[CoroutineInfo::corotineEntry exception:" << ex.what() << endl); } catch(...) { - TLOGERROR("[TARS][CoroutineInfo::corotineEntry unknown exception." << endl); + TLOGERROR("[CoroutineInfo::corotineEntry unknown exception." << endl); } } @@ -309,11 +309,11 @@ void CoroutineInfo::corotineProc(void * args, transfer_t t) } catch(std::exception &ex) { - TLOGERROR("[TARS][CoroutineInfo::corotineProc exception:" << ex.what() << endl); + TLOGERROR("[CoroutineInfo::corotineProc exception:" << ex.what() << endl); } catch(...) { - TLOGERROR("[TARS][CoroutineInfo::corotineProc unknown exception." << endl); + TLOGERROR("[CoroutineInfo::corotineProc unknown exception." << endl); } CoroutineScheduler* scheduler = coro->getScheduler(); @@ -322,7 +322,7 @@ void CoroutineInfo::corotineProc(void * args, transfer_t t) scheduler->switchCoro(&(scheduler->getMainCoroutine())); // scheduler->switchCoro(coro, &(scheduler->getMainCoroutine())); - TLOGERROR("[TARS][CoroutineInfo::corotineProc no come." << endl); + TLOGERROR("[CoroutineInfo::corotineProc no come." << endl); } ////////////////////////////////////////////////////////////// @@ -357,7 +357,7 @@ void CoroutineScheduler::init(uint32_t iPoolSize, size_t iStackSize) { if(iPoolSize <= 0) { - TLOGERROR("[TARS][[CoroutineScheduler::init iPoolSize <= 0." << endl); + TLOGERROR("[CoroutineScheduler::init iPoolSize <= 0." << endl); return ; } @@ -396,7 +396,7 @@ void CoroutineScheduler::init(uint32_t iPoolSize, size_t iStackSize) // int ret = _alloc.allocate(s_ctx, iStackSize); // if(ret != 0) // { - // TLOGERROR("[TARS][CoroutineScheduler::init iPoolSize:" << iPoolSize << "|iStackSize:" << iStackSize << "|i:" << i << endl); + // TLOGERROR("[CoroutineScheduler::init iPoolSize:" << iPoolSize << "|iStackSize:" << iStackSize << "|i:" << i << endl); // delete coro; // coro = NULL; @@ -429,7 +429,7 @@ void CoroutineScheduler::init(uint32_t iPoolSize, size_t iStackSize) _currentCoro = &_mainCoro; - TLOGDEBUG("[TARS][CoroutineScheduler::init iPoolSize:" << _poolSize << "|iCurrentSize:" << _currentSize << "|iStackSize:" << _stackSize << endl); + TLOGDEBUG("[CoroutineScheduler::init iPoolSize:" << _poolSize << "|iCurrentSize:" << _currentSize << "|iStackSize:" << _stackSize << endl); } int CoroutineScheduler::increaseCoroPoolSize() @@ -437,7 +437,7 @@ int CoroutineScheduler::increaseCoroPoolSize() int iInc = ((_poolSize - _currentSize) > 100) ? 100 : (_poolSize - _currentSize); if(iInc <= 0) { - TLOGERROR("[TARS][CoroutineScheduler::increaseCoroPoolSize full iPoolSize:" << _poolSize << "|iCurrentSize:" << _currentSize << endl); + TLOGERROR("[CoroutineScheduler::increaseCoroPoolSize full iPoolSize:" << _poolSize << "|iCurrentSize:" << _currentSize << endl); return -1; } @@ -453,7 +453,7 @@ int CoroutineScheduler::increaseCoroPoolSize() // int ret = _alloc.allocate(s_ctx, _stackSize); // if(ret != 0) // { - // TLOGERROR("[TARS][CoroutineScheduler::increaseCoroPoolSize iPoolSize:" << _poolSize << "|iStackSize:" << _stackSize << "|i:" << i << endl); + // TLOGERROR("[CoroutineScheduler::increaseCoroPoolSize iPoolSize:" << _poolSize << "|iStackSize:" << _stackSize << "|i:" << i << endl); // delete coro; // coro = NULL; @@ -473,7 +473,7 @@ int CoroutineScheduler::increaseCoroPoolSize() if(iSucc == 0) { - TLOGERROR("[TARS][CoroutineScheduler::increaseCoroPoolSize cannot create iInc:" << iInc << "|iPoolSize:" << _poolSize << endl); + TLOGERROR("[CoroutineScheduler::increaseCoroPoolSize cannot create iInc:" << iInc << "|iPoolSize:" << _poolSize << endl); return -1; } @@ -792,7 +792,7 @@ void CoroutineScheduler::moveToActive(CoroutineInfo *coro, bool bFlag) } else { - TLOGERROR("[TARS][CoroutineScheduler::moveToActive ERROR|iCoroId:" << coro->getUid() << "|tyep:" << coro->getStatus() << endl); + TLOGERROR("[CoroutineScheduler::moveToActive ERROR|iCoroId:" << coro->getUid() << "|tyep:" << coro->getStatus() << endl); } } @@ -806,7 +806,7 @@ void CoroutineScheduler::moveToAvail(CoroutineInfo *coro) } else { - TLOGERROR("[TARS][CoroutineScheduler::moveToAvail ERROR:|iCoroId:" << coro->getUid() << "|tyep:" << coro->getStatus() << endl); + TLOGERROR("[CoroutineScheduler::moveToAvail ERROR:|iCoroId:" << coro->getUid() << "|tyep:" << coro->getStatus() << endl); } } @@ -826,7 +826,7 @@ void CoroutineScheduler::moveToInactive(CoroutineInfo *coro) } else { - TLOGERROR("[TARS][CoroutineScheduler::moveToInactive ERROR|iCoroId:" << coro->getUid() << "|tyep:" << coro->getStatus() << endl); + TLOGERROR("[CoroutineScheduler::moveToInactive ERROR|iCoroId:" << coro->getUid() << "|tyep:" << coro->getStatus() << endl); } } @@ -846,7 +846,7 @@ void CoroutineScheduler::moveToTimeout(CoroutineInfo *coro) } else { - TLOGERROR("[TARS][CoroutineScheduler::moveToTimeout ERROR|iCoroId:" << coro->getUid() << "|tyep:" << coro->getStatus() << endl); + TLOGERROR("[CoroutineScheduler::moveToTimeout ERROR|iCoroId:" << coro->getUid() << "|tyep:" << coro->getStatus() << endl); } } @@ -878,7 +878,7 @@ void CoroutineScheduler::moveToFreeList(CoroutineInfo *coro) } else { - TLOGERROR("[TARS][CoroutineScheduler::moveToFreeList ERROR: already free|iCoroId:" << coro->getUid() << "|tyep:" << coro->getStatus() << endl); + TLOGERROR("[CoroutineScheduler::moveToFreeList ERROR: already free|iCoroId:" << coro->getUid() << "|tyep:" << coro->getStatus() << endl); } } @@ -970,11 +970,11 @@ void Coroutine::coroEntry(Coroutine *pCoro) } catch(exception &ex) { - TLOGERROR("[TARS][[Coroutine::coroEntry exception:" << ex.what() << "]" << endl); + TLOGERROR("[Coroutine::coroEntry exception:" << ex.what() << "]" << endl); } catch(...) { - TLOGERROR("[TARS][[Coroutine::coroEntry unknown exception]" << endl); + TLOGERROR("[Coroutine::coroEntry unknown exception]" << endl); } } @@ -986,7 +986,7 @@ uint32_t Coroutine::createCoroutine(const std::function &coroFunc) } else { - TLOGERROR("[TARS][[Coroutine::createCoroutine coro sched no init]" << endl); + TLOGERROR("[Coroutine::createCoroutine coro sched no init]" << endl); } return -1; } @@ -999,7 +999,7 @@ void Coroutine::yield() } else { - throw CoroutineException("[TARS][[Coroutine::yield coro sched no init]"); + throw CoroutineException("[Coroutine::yield coro sched no init]"); } } @@ -1011,7 +1011,7 @@ void Coroutine::Sleep(int iSleepTime) } else { - throw CoroutineException("[TARS][[Coroutine::yield coro sched no init]"); + throw CoroutineException("[Coroutine::yield coro sched no init]"); } } diff --git a/servant/libservant/TarsCurrent.cpp b/servant/libservant/Current.cpp similarity index 76% rename from servant/libservant/TarsCurrent.cpp rename to servant/libservant/Current.cpp index e8c9f30a5eb50408cebd2972b12bd18b2a7db8f5..48669cbe2658ca3268538be23159381e1fea492c 100644 --- a/servant/libservant/TarsCurrent.cpp +++ b/servant/libservant/Current.cpp @@ -14,7 +14,7 @@ * specific language governing permissions and limitations under the License. */ -#include "servant/TarsCurrent.h" +#include "servant/Current.h" #include "servant/ServantHandle.h" #include "servant/BaseF.h" #include "servant/Application.h" @@ -24,7 +24,7 @@ namespace tars { ////////////////////////////////////////////////////////////////// -TarsCurrent::TarsCurrent(ServantHandle *pServantHandle) +Current::Current(ServantHandle *pServantHandle) : _servantHandle(pServantHandle) // , _bindAdapter(NULL) // , _uid(0) @@ -39,7 +39,7 @@ TarsCurrent::TarsCurrent(ServantHandle *pServantHandle) { } -TarsCurrent::~TarsCurrent() +Current::~Current() { //TUP调用或单向调用,从服务端上报调用信息 if(_reportStat) @@ -60,65 +60,75 @@ TarsCurrent::~TarsCurrent() } } -const string &TarsCurrent::getIp() const +const string &Current::getHostName() const { - return _data->ip(); - // return _ip; + auto it = _request.context.find("node_name"); + if(it != _request.context.end()) + { + return it->second; + } + return _data->ip(); + } -int TarsCurrent::getPort() const +const string &Current::getIp() const +{ + return _data->ip(); +} + +int Current::getPort() const { return _data->port(); // return _port; } -uint32_t TarsCurrent::getUId() const +uint32_t Current::getUId() const { return _data->uid(); // return _uid; } -string TarsCurrent::getServantName() const +string Current::getServantName() const { return _request.sServantName; } -short TarsCurrent::getRequestVersion() const +short Current::getRequestVersion() const { return _request.iVersion; } -map& TarsCurrent::getContext() +map& Current::getContext() { return _request.context; } -const map& TarsCurrent::getRequestStatus() const +const map& Current::getRequestStatus() const { return _request.status; } -string TarsCurrent::getFuncName() const +string Current::getFuncName() const { return _request.sFuncName; } -uint32_t TarsCurrent::getRequestId() const +uint32_t Current::getRequestId() const { return _request.iRequestId; } -char TarsCurrent::getPacketType() const +char Current::getPacketType() const { return _request.cPacketType; } -tars::Int32 TarsCurrent::getMessageType() const +tars::Int32 Current::getMessageType() const { return _request.iMessageType; } -struct timeval TarsCurrent::getRecvTime() const +struct timeval Current::getRecvTime() const { timeval tm; tm.tv_sec = _data->recvTimeStamp()/1000; @@ -127,12 +137,12 @@ struct timeval TarsCurrent::getRecvTime() const return tm; } -void TarsCurrent::setReportStat(bool bReport) +void Current::setReportStat(bool bReport) { _reportStat = bReport; } -const vector& TarsCurrent::getRequestBuffer() const +const vector& Current::getRequestBuffer() const { if (_data->adapter()->isTarsProtocol()) { @@ -146,23 +156,23 @@ const vector& TarsCurrent::getRequestBuffer() const // return _request.sBuffer; } -bool TarsCurrent::isResponse() const +bool Current::isResponse() const { return _response; } -void TarsCurrent::setCloseType(int type) +void Current::setCloseType(int type) { _data->setCloseType(type); } -int TarsCurrent::getCloseType() const +int Current::getCloseType() const { return _data->closeType(); } -void TarsCurrent::initialize(const shared_ptr &data) -// void TarsCurrent::initialize(const TC_EpollServer::tagRecvData &stRecvData) +void Current::initialize(const shared_ptr &data) +// void Current::initialize(const TC_EpollServer::tagRecvData &stRecvData) { _data = data; @@ -176,7 +186,7 @@ void TarsCurrent::initialize(const shared_ptr &data } -void TarsCurrent::initializeClose(const shared_ptr &data) +void Current::initializeClose(const shared_ptr &data) { _data = data; @@ -184,7 +194,7 @@ void TarsCurrent::initializeClose(const shared_ptr } -void TarsCurrent::initialize(const vector& sRecvBuffer) +void Current::initialize(const vector& sRecvBuffer) { TarsInputStream is; @@ -193,7 +203,7 @@ void TarsCurrent::initialize(const vector& sRecvBuffer) _request.readFrom(is); } -// void TarsCurrent::initialize(const TC_EpollServer::tagRecvData &stRecvData, int64_t beginTime) +// void Current::initialize(const TC_EpollServer::tagRecvData &stRecvData, int64_t beginTime) // { // _ip = stRecvData.ip; @@ -223,7 +233,7 @@ void TarsCurrent::initialize(const vector& sRecvBuffer) // } // } -// void TarsCurrent::initializeClose(const TC_EpollServer::tagRecvData &stRecvData) +// void Current::initializeClose(const TC_EpollServer::tagRecvData &stRecvData) // { // _ip = stRecvData.ip; @@ -240,7 +250,7 @@ void TarsCurrent::initialize(const vector& sRecvBuffer) // _begintime = TNOWMS; // } -// void TarsCurrent::initialize(const string &sRecvBuffer) +// void Current::initialize(const string &sRecvBuffer) // { // TarsInputStream is; @@ -249,7 +259,7 @@ void TarsCurrent::initialize(const vector& sRecvBuffer) // _request.readFrom(is); // } -void TarsCurrent::sendResponse(const char* buff, uint32_t len) +void Current::sendResponse(const char* buff, uint32_t len) { // _servantHandle->sendResponse(_uid, string(buff, len), _ip, _port, _fd); shared_ptr send = _data->createSendContext(); @@ -258,7 +268,7 @@ void TarsCurrent::sendResponse(const char* buff, uint32_t len) } -void TarsCurrent::sendResponse(int iRet, const vector &buff) +void Current::sendResponse(int iRet, const vector &buff) { //单向调用不需要返回 if (_request.cPacketType == TARSONEWAY) @@ -271,27 +281,27 @@ void TarsCurrent::sendResponse(int iRet, const vector &buff) sendResponse(iRet, buff, TARS_STATUS(), ""); } -void TarsCurrent::sendResponse(int iRet) +void Current::sendResponse(int iRet) { // ResponsePacket response; sendResponse(iRet, vector(), TARS_STATUS(), ""); } -void TarsCurrent::sendResponse(int iRet, tars::TarsOutputStream& os) +void Current::sendResponse(int iRet, tars::TarsOutputStream& os) { // ResponsePacket response; // os.swap(response.sBuffer); sendResponse(iRet, os.getByteBuffer(), TARS_STATUS(), ""); } -void TarsCurrent::sendResponse(int iRet, tup::UniAttribute& attr) +void Current::sendResponse(int iRet, tup::UniAttribute& attr) { ResponsePacket response; attr.encode(response.sBuffer); sendResponse(iRet, response.sBuffer, TARS_STATUS(), ""); } -void TarsCurrent::sendResponse(int iRet, const vector &buffer, const map& status, const string & sResultDesc) +void Current::sendResponse(int iRet, const vector &buffer, const map& status, const string & sResultDesc) { _ret = iRet; @@ -325,7 +335,7 @@ void TarsCurrent::sendResponse(int iRet, const vector &buffer, const map< response.context = _responseContext; response.iRet = iRet; - TLOGTARS("[TARS]TarsCurrent::sendResponse :" + TLOGTARS("Current::sendResponse :" << response.iMessageType << "|" << _request.sServantName << "|" << _request.sFuncName << "|" @@ -367,7 +377,7 @@ void TarsCurrent::sendResponse(int iRet, const vector &buffer, const map< response.status[ServantProxy::STATUS_RESULT_DESC] = sResultDesc; } - TLOGTARS("[TARS]TarsCurrent::sendResponse :" + TLOGTARS("Current::sendResponse :" << response.iMessageType << "|" << _request.sServantName << "|" << _request.sFuncName << "|" @@ -389,7 +399,7 @@ void TarsCurrent::sendResponse(int iRet, const vector &buffer, const map< } -void TarsCurrent::close() +void Current::close() { if (_servantHandle) { @@ -397,17 +407,17 @@ void TarsCurrent::close() } } -ServantHandle* TarsCurrent::getServantHandle() +ServantHandle* Current::getServantHandle() { return _servantHandle; } -TC_EpollServer::BindAdapter* TarsCurrent::getBindAdapter() +TC_EpollServer::BindAdapter* Current::getBindAdapter() { return _data->adapter().get(); } -void TarsCurrent::reportToStat(const string& sObj) +void Current::reportToStat(const string& sObj) { StatReport* stat = Application::getCommunicator()->getStatReport(); @@ -417,7 +427,9 @@ void TarsCurrent::reportToStat(const string& sObj) // int sptime = endtime - _begintime; //被调上报自己的set信息,set信息在setReportInfo设置 - stat->report(sObj, "" , _request.sServantName, _data->ip(), 0, _request.sFuncName, (StatReport::StatResult)_ret, TNOWMS - _data->recvTimeStamp(), 0); + // stat->report(sObj, "" , _request.sServantName, _data->ip(), 0, _request.sFuncName, (StatReport::StatResult)_ret, TNOWMS - _data->recvTimeStamp(), 0); + + stat->report(sObj, "", _request.sFuncName, _data->ip(), 0, (StatReport::StatResult)_ret, TNOWMS - _data->recvTimeStamp(), 0, false); } } diff --git a/servant/libservant/EndpointInfo.cpp b/servant/libservant/EndpointInfo.cpp index 2d48fff2d108d432fa7d309df264698cd15e1690..d851d830bb7fd1cc36a70dd3777ee405fad65017 100755 --- a/servant/libservant/EndpointInfo.cpp +++ b/servant/libservant/EndpointInfo.cpp @@ -15,7 +15,7 @@ */ #include "servant/EndpointInfo.h" -#include "servant/TarsLogger.h" +#include "servant/RemoteLogger.h" #include "servant/NetworkUtil.h" #include "util/tc_socket.h" diff --git a/servant/libservant/EndpointManager.cpp b/servant/libservant/EndpointManager.cpp index fbbf2aef2032c8c004a674cfde5de8066760c86d..6d3e85c3ee63bc4b4ecc7f23ed0142ec2b3897fe 100644 --- a/servant/libservant/EndpointManager.cpp +++ b/servant/libservant/EndpointManager.cpp @@ -16,7 +16,7 @@ #include "util/tc_port.h" #include "servant/EndpointManager.h" #include "servant/ObjectProxy.h" -#include "servant/TarsLogger.h" +#include "servant/RemoteLogger.h" #include "servant/AppCache.h" #include "servant/Application.h" #include "servant/StatReport.h" @@ -34,6 +34,7 @@ QueryEpBase::QueryEpBase(Communicator * pComm, bool bFirstNetThread,bool bInterf , _locator("") , _valid(false) , _weightType(E_LOOP) +, _rootServant(true) , _requestRegistry(false) , _requestTimeout(0) , _timeoutInterval(5*1000) @@ -50,7 +51,7 @@ QueryEpBase::QueryEpBase(Communicator * pComm, bool bFirstNetThread,bool bInterf void QueryEpBase::callback_findObjectById4All(Int32 ret, const vector& activeEp, const vector& inactiveEp) { - TLOGTARS("[TARS][callback_findObjectById4All _objName:" << _objName << "|ret:" << ret + TLOGTARS("[callback_findObjectById4All _objName:" << _objName << "|ret:" << ret << ",active:" << activeEp.size() << ",inactive:" << inactiveEp.size() << "]" << endl); @@ -59,14 +60,14 @@ void QueryEpBase::callback_findObjectById4All(Int32 ret, const vector void QueryEpBase::callback_findObjectById4All_exception(Int32 ret) { - TLOGERROR("[TARS][callback_findObjectById4All_exception _objName:" << _objName << "|ret:" << ret << "]" << endl); + TLOGERROR("[callback_findObjectById4All_exception _objName:" << _objName << "|ret:" << ret << "]" << endl); doEndpointsExp(ret); } void QueryEpBase::callback_findObjectById4Any(Int32 ret, const vector& activeEp, const vector& inactiveEp) { - TLOGTARS("[TARS][callback_findObjectById4Any _objName:" << _objName << "|ret:" << ret + TLOGTARS("[callback_findObjectById4Any _objName:" << _objName << "|ret:" << ret << ",active:" << activeEp.size() << ",inactive:" << inactiveEp.size() << "]" << endl); @@ -75,14 +76,14 @@ void QueryEpBase::callback_findObjectById4Any(Int32 ret, const vector void QueryEpBase::callback_findObjectById4Any_exception(Int32 ret) { - TLOGERROR("[TARS][callback_findObjectById4Any_exception _objName:" << _objName << "|ret:" << ret << "]" << endl); + TLOGERROR("[callback_findObjectById4Any_exception _objName:" << _objName << "|ret:" << ret << "]" << endl); doEndpointsExp(ret); } void QueryEpBase::callback_findObjectByIdInSameGroup(Int32 ret, const vector& activeEp, const vector& inactiveEp) { - TLOGTARS("[TARS][callback_findObjectByIdInSameGroup _objName:" << _objName << "|ret:"< &activeEp, const vector & inactiveEp) { - TLOGTARS("[TARS][callback_findObjectByIdInSameSet _objName:" << _objName << "|ret:" << ret + TLOGTARS("[callback_findObjectByIdInSameSet _objName:" << _objName << "|ret:" << ret << ",active:" << activeEp.size() << ",inactive:" << inactiveEp.size() << "]" << endl); @@ -107,14 +108,14 @@ void QueryEpBase::callback_findObjectByIdInSameSet( Int32 ret, const vector &activeEp, const vector &inactiveEp) { - TLOGTARS("[TARS][callback_findObjectByIdInSameStation _objName:" << _objName << "|ret:" << ret + TLOGTARS("[callback_findObjectByIdInSameStation _objName:" << _objName << "|ret:" << ret << ",active:" << activeEp.size() << ",inactive:" << inactiveEp.size() << "]" << endl); @@ -123,7 +124,7 @@ void QueryEpBase::callback_findObjectByIdInSameStation( Int32 ret, const vector< void QueryEpBase::callback_findObjectByIdInSameStation_exception( Int32 ret) { - TLOGERROR("[TARS][callback_findObjectByIdInSameStation_exception _objName:" << _objName << "|ret:" << ret << "]" << endl); + TLOGERROR("[callback_findObjectByIdInSameStation_exception _objName:" << _objName << "|ret:" << ret << "]" << endl); doEndpointsExp(ret); } @@ -137,7 +138,7 @@ int QueryEpBase::setLocatorPrx(QueryFPrx prx) bool QueryEpBase::init(const string & sObjName,const string & sLocator,const string& setName) { - TLOGTARS("[TARS][QueryEpBase::init sObjName:" << sObjName << ",sLocator:" << sLocator << ",setName:" << setName << "]" << endl); + TLOGTARS("[QueryEpBase::init sObjName:" << sObjName << ",sLocator:" << sLocator << ",setName:" << setName << "]" << endl); _locator = sLocator; @@ -158,12 +159,19 @@ void QueryEpBase::setObjName(const string & sObjName) if (pos != string::npos) { //[直接连接]指定服务的IP和端口列表 - _objName = sObjName.substr(0,pos); sEndpoints = sObjName.substr(pos + 1); - _direct = true; + pos = _objName.find_first_of("#"); + + if(pos != string::npos) + { + _rootServant = false; + _objName = _objName.substr(0, pos); + } + + _direct = true; _valid = true; } @@ -178,10 +186,17 @@ void QueryEpBase::setObjName(const string & sObjName) if(_locator.find_first_not_of('@') == string::npos) { - TLOGERROR("[TARS][QueryEpBase::setObjName locator is not valid,_locator:" << _locator << "]" << endl); + TLOGERROR("[QueryEpBase::setObjName locator is not valid,_locator:" << _locator << "]" << endl); throw TarsRegistryException("locator is not valid,_locator:" + _locator); } + pos = _objName.find_first_of("#"); + if(pos != string::npos) + { + _objName = _objName.substr(0, pos); + } + + _queryFPrx = _communicator->stringToProxy(_locator); string sLocatorKey = _locator; @@ -327,7 +342,7 @@ void QueryEpBase::setEndpoints(const string & sEndpoints, set & se } catch (...) { - TLOGERROR("[TARS][QueryEpBase::setEndpoints parse error,objname:" << _objName << ",endpoint:" << vEndpoints[i] << "]" << endl); + TLOGERROR("[QueryEpBase::setEndpoints parse error,objname:" << _objName << ",endpoint:" << vEndpoints[i] << "]" << endl); } } @@ -372,12 +387,15 @@ void QueryEpBase::refreshReg(GetEndpointType type, const string & sName) //一定时间不回调就算超时了 _requestTimeout = iNow + _timeoutInterval; - TLOGTARS("[TARS][QueryEpBase::refresh,"<<_objName<<"]"<findObjectById4Any(_objName,activeEp,inactiveEp); + iRet = _queryFPrx->findObjectById4Any(_objName,activeEp,inactiveEp, ServerConfig::Context); break; } case E_STATION: { - iRet = _queryFPrx->findObjectByIdInSameStation(_objName,sName,activeEp,inactiveEp); + iRet = _queryFPrx->findObjectByIdInSameStation(_objName,sName,activeEp,inactiveEp, ServerConfig::Context); } case E_SET: { - iRet = _queryFPrx->findObjectByIdInSameSet(_objName,sName,activeEp,inactiveEp); + iRet = _queryFPrx->findObjectByIdInSameSet(_objName,sName,activeEp,inactiveEp, ServerConfig::Context); break; } case E_DEFAULT: @@ -408,11 +426,11 @@ void QueryEpBase::refreshReg(GetEndpointType type, const string & sName) { //指定set调用时,指定set的优先级最高 string setId = _invokeSetId.empty()?ClientConfig::SetDivision:_invokeSetId; - iRet = _queryFPrx->findObjectByIdInSameSet(_objName,setId,activeEp,inactiveEp); + iRet = _queryFPrx->findObjectByIdInSameSet(_objName,setId,activeEp,inactiveEp, ServerConfig::Context); } else { - iRet = _queryFPrx->findObjectByIdInSameGroup(_objName,activeEp,inactiveEp); + iRet = _queryFPrx->findObjectByIdInSameGroup(_objName,activeEp,inactiveEp, ServerConfig::Context); } break; } @@ -425,17 +443,17 @@ void QueryEpBase::refreshReg(GetEndpointType type, const string & sName) { case E_ALL: { - _queryFPrx->async_findObjectById4Any(this,_objName); + _queryFPrx->async_findObjectById4Any(this,_objName, ServerConfig::Context); break; } case E_STATION: { - _queryFPrx->async_findObjectByIdInSameStation(this,_objName,sName); + _queryFPrx->async_findObjectByIdInSameStation(this,_objName,sName, ServerConfig::Context); break; } case E_SET: { - _queryFPrx->async_findObjectByIdInSameSet(this,_objName,sName); + _queryFPrx->async_findObjectByIdInSameSet(this,_objName,sName, ServerConfig::Context); break; } case E_DEFAULT: @@ -445,11 +463,11 @@ void QueryEpBase::refreshReg(GetEndpointType type, const string & sName) { //指定set调用时,指定set的优先级最高 string setId = _invokeSetId.empty()?ClientConfig::SetDivision:_invokeSetId; - _queryFPrx->async_findObjectByIdInSameSet(this,_objName,setId); + _queryFPrx->async_findObjectByIdInSameSet(this,_objName,setId, ServerConfig::Context); } else { - _queryFPrx->async_findObjectByIdInSameGroup(this,_objName); + _queryFPrx->async_findObjectByIdInSameGroup(this,_objName, ServerConfig::Context); } break; } @@ -458,12 +476,12 @@ void QueryEpBase::refreshReg(GetEndpointType type, const string & sName) } catch(TC_Exception & ex) { - TLOGERROR("[TARS]QueryEpBase::refreshReg obj:"<<_objName<<"exception:"<& activeEp, const vectorset(objName,sEndpoints,sLocatorKey); } - TLOGTARS("[TARS][setEndPointToCache,obj:" << _objName << ",invokeSetId:" << _invokeSetId << ",endpoint:" << sEndpoints << "]" << endl); + TLOGTARS("[setEndPointToCache,obj:" << _objName << ",invokeSetId:" << _invokeSetId << ",endpoint:" << sEndpoints << "]" << endl); } ///////////////////////////////////////////////////////////////////////////// @@ -704,7 +722,7 @@ EndpointManager::~EndpointManager() } } -void EndpointManager::notifyEndpoints(const set & active, const set & inactive, bool bSync) +void EndpointManager::updateEndpoints(const set & active, const set & inactive) { set::const_iterator iter; map::iterator iterAdapter; @@ -788,6 +806,13 @@ void EndpointManager::notifyEndpoints(const set & active, const se _update = true; } +void EndpointManager::notifyEndpoints(const set & active,const set & inactive,bool bNotify) +{ + updateEndpoints(active, inactive); + + _objectProxy->onNotifyEndpoints(active, inactive); +} + void EndpointManager::doNotify() { _objectProxy->doInvoke(); @@ -840,7 +865,7 @@ AdapterProxy * EndpointManager::getNextValidProxy(bool onlyCheck) { if (_activeProxys.empty()) { - TLOGERROR("[TARS][EndpointManager::getNextValidProxy activeEndpoints is empty][obj:"<<_objName<<"]" << endl); + TLOGERROR("[EndpointManager::getNextValidProxy activeEndpoints is empty][obj:"<<_objName<<"]" << endl); return NULL; } @@ -913,7 +938,7 @@ AdapterProxy* EndpointManager::getHashProxyForWeight(int64_t hashCode, bool bSta { if(_vRegProxys.empty()) { - TLOGERROR("[TARS][EndpointManager::getHashProxyForWeight _vRegProxys is empty], bStatic:" << bStatic << endl); + TLOGERROR("[EndpointManager::getHashProxyForWeight _vRegProxys is empty], bStatic:" << bStatic << endl); return NULL; } @@ -925,7 +950,7 @@ AdapterProxy* EndpointManager::getHashProxyForWeight(int64_t hashCode, bool bSta int64_t iEnd = TNOWMS; - TLOGTARS("[TARS][EndpointManager::getHashProxyForWeight update bStatic:" << bStatic << "|_objName:" << _objName << "|timecost(ms):" << (iEnd - iBegin) << endl); + TLOGTARS("[EndpointManager::getHashProxyForWeight update bStatic:" << bStatic << "|_objName:" << _objName << "|timecost(ms):" << (iEnd - iBegin) << endl); } if(vRouterCache.size() > 0) @@ -954,7 +979,7 @@ AdapterProxy* EndpointManager::getHashProxyForWeight(int64_t hashCode, bool bSta { if(_activeProxys.empty()) { - TLOGERROR("[TARS][EndpointManager::getHashProxyForWeight _activeEndpoints is empty], bStatic:" << bStatic << endl); + TLOGERROR("[EndpointManager::getHashProxyForWeight _activeEndpoints is empty], bStatic:" << bStatic << endl); return NULL; } @@ -1022,7 +1047,7 @@ AdapterProxy* EndpointManager::getConHashProxyForWeight(int64_t hashCode, bool b { if(_vRegProxys.empty()) { - TLOGERROR("[TARS][EndpointManager::getConHashProxyForWeight _vRegProxys is empty], bStatic:" << bStatic << endl); + TLOGERROR("[EndpointManager::getConHashProxyForWeight _vRegProxys is empty], bStatic:" << bStatic << endl); return NULL; } @@ -1034,7 +1059,7 @@ AdapterProxy* EndpointManager::getConHashProxyForWeight(int64_t hashCode, bool b int64_t iEnd = TNOWMS; - TLOGTARS("[TARS][EndpointManager::getConHashProxyForWeight update bStatic:" << bStatic << "|_objName:" << _objName << "|timecost(ms):" << (iEnd - iBegin) << endl); + TLOGTARS("[EndpointManager::getConHashProxyForWeight update bStatic:" << bStatic << "|_objName:" << _objName << "|timecost(ms):" << (iEnd - iBegin) << endl); } if(_consistentHashWeight.size() > 0) @@ -1058,7 +1083,7 @@ AdapterProxy* EndpointManager::getConHashProxyForWeight(int64_t hashCode, bool b { if(_activeProxys.empty()) { - TLOGERROR("[TARS][EndpointManager::getConHashProxyForWeight _activeEndpoints is empty], bStatic:" << bStatic << endl); + TLOGERROR("[EndpointManager::getConHashProxyForWeight _activeEndpoints is empty], bStatic:" << bStatic << endl); return NULL; } @@ -1172,7 +1197,7 @@ void EndpointManager::updateHashProxyWeighted(bool bStatic) { if(_vRegProxys.size() <= 0) { - TLOGERROR("[TARS][EndpointManager::updateHashProxyWeighted _vRegProxys is empty], bStatic:" << bStatic << endl); + TLOGERROR("[EndpointManager::updateHashProxyWeighted _vRegProxys is empty], bStatic:" << bStatic << endl); return ; } @@ -1195,7 +1220,7 @@ void EndpointManager::updateHashProxyWeighted(bool bStatic) if(vRegProxys.size() <= 0) { - TLOGERROR("[TARS][EndpointManager::updateHashProxyWeighted vRegProxys is empty], bStatic:" << bStatic << endl); + TLOGERROR("[EndpointManager::updateHashProxyWeighted vRegProxys is empty], bStatic:" << bStatic << endl); return ; } @@ -1260,7 +1285,7 @@ void EndpointManager::updateHashProxyWeighted(bool bStatic) } } - TLOGTARS("[TARS]EndpointManager::updateHashProxyWeighted bStatic:" << bStatic << "|_objName:" << _objName << "|endpoint:" << vRegProxys[i]->endpoint().desc() << "|iWeight:" << vRegProxys[i]->getWeight() << "|iWeightR:" << iWeight << "|iIndex:" << vIndex[i] << endl); + TLOGTARS("EndpointManager::updateHashProxyWeighted bStatic:" << bStatic << "|_objName:" << _objName << "|endpoint:" << vRegProxys[i]->endpoint().desc() << "|iWeight:" << vRegProxys[i]->getWeight() << "|iWeightR:" << iWeight << "|iIndex:" << vIndex[i] << endl); } for(size_t i = 0; i < iMaxRouterR; i++) @@ -1297,7 +1322,7 @@ void EndpointManager::updateConHashProxyWeighted(bool bStatic, vector 0) @@ -1447,7 +1472,7 @@ AdapterProxy* EndpointManager::getConHashProxyForNormal(int64_t hashCode, bool o { if(_activeProxys.empty()) { - TLOGERROR("[TARS][EndpointManager::getConHashProxyForNormal _activeEndpoints is empty]" << endl); + TLOGERROR("[EndpointManager::getConHashProxyForNormal _activeEndpoints is empty]" << endl); return NULL; } @@ -1518,7 +1543,7 @@ AdapterProxy* EndpointManager::getWeightedForNormal(bool bStaticWeighted, bool o { if (_activeProxys.empty()) { - TLOGERROR("[TARS][EndpointManager::getWeightedForNormal activeEndpoints is empty][obj:"<<_objName<<"]" << endl); + TLOGERROR("[EndpointManager::getWeightedForNormal activeEndpoints is empty][obj:"<<_objName<<"]" << endl); return NULL; } @@ -1646,7 +1671,7 @@ void EndpointManager::updateProxyWeighted() if(iWeightProxySize <= 0) { - TLOGERROR("[TARS]EndpointManager::updateProxyWeighted _objName:" << _objName << "|_activeProxys.size() <= 0" << endl); + TLOGERROR("[EndpointManager::updateProxyWeighted _objName:" << _objName << ", activeProxys.size() <= 0]" << endl); return ; } @@ -1664,7 +1689,7 @@ void EndpointManager::updateProxyWeighted() if(iWeightProxySize <= 0) { - TLOGERROR("[TARS]EndpointManager::updateProxyWeighted _objName:" << _objName << "|vProxy.size() <= 0" << endl); + TLOGERROR("[EndpointManager::updateProxyWeighted _objName:" << _objName << ", vProxy.size() <= 0]" << endl); return ; } @@ -1697,7 +1722,7 @@ void EndpointManager::dispatchEndpointCache(const vector &vWeight) { if(vWeight.size() <= 0) { - TLOGERROR("EndpointManager::dispatchEndpointCache vWeight.size() < 0" << endl); + TLOGERROR("[EndpointManager::dispatchEndpointCache vWeight.size() < 0]" << endl); return ; } @@ -1771,7 +1796,7 @@ void EndpointManager::dispatchEndpointCache(const vector &vWeight) _staticRouterCache.push_back(i); } - TLOGTARS("[TARS]EndpointManager::dispatchEndpointCache _objName:" << _objName << "|endpoint:" << _activeWeightProxy[i]->endpoint().desc() << "|iWeightR:" << iWeight << endl); + TLOGTARS("EndpointManager::dispatchEndpointCache _objName:" << _objName << "|endpoint:" << _activeWeightProxy[i]->endpoint().desc() << "|iWeightR:" << iWeight << endl); } for(size_t i = 0; i < iMaxRouterR; i++) diff --git a/servant/libservant/TarsNodeF.cpp b/servant/libservant/KeepAliveNodeF.cpp similarity index 69% rename from servant/libservant/TarsNodeF.cpp rename to servant/libservant/KeepAliveNodeF.cpp index a0aa12cf20a977269235f377f75a91c203ff383b..430b0ee5484da5b1f8409547da98ec8d502d3fbb 100755 --- a/servant/libservant/TarsNodeF.cpp +++ b/servant/libservant/KeepAliveNodeF.cpp @@ -15,14 +15,14 @@ */ #include "util/tc_port.h" -#include "servant/TarsNodeF.h" -#include "servant/TarsLogger.h" +#include "servant/KeepAliveNodeF.h" +#include "servant/RemoteLogger.h" #include "servant/Communicator.h" namespace tars { -void TarsNodeFHelper::setNodeInfo(const CommunicatorPtr &comm, const string &obj, const string &app, const string &server) +void KeepAliveNodeFHelper::setNodeInfo(const CommunicatorPtr &comm, const string &obj, const string &app, const string &server) { _comm = comm; if(!obj.empty()) @@ -35,7 +35,7 @@ void TarsNodeFHelper::setNodeInfo(const CommunicatorPtr &comm, const string &obj _si.pid = TC_Port::getpid(); } -void TarsNodeFHelper::keepAlive(const string &adapter) +void KeepAliveNodeFHelper::keepAlive(const string &adapter) { try { @@ -66,15 +66,15 @@ void TarsNodeFHelper::keepAlive(const string &adapter) } catch(exception &ex) { - TLOGERROR("TarsNodeFHelper::keepAlive error:" << ex.what() << endl); + TLOGERROR("KeepAliveNodeFHelper::keepAlive error:" << ex.what() << endl); } catch(...) { - TLOGERROR("TarsNodeFHelper::keepAlive unknown error" << endl); + TLOGERROR("KeepAliveNodeFHelper::keepAlive unknown error" << endl); } } -void TarsNodeFHelper::keepActiving() +void KeepAliveNodeFHelper::keepActiving() { try { @@ -85,31 +85,31 @@ void TarsNodeFHelper::keepActiving() } catch(exception &ex) { - LOG->error() << "TafNodeFHelper::keepAlive error:" << ex.what() << endl; + TLOGERROR("[KeepAliveNodeFHelper::keepAlive error:" << ex.what() << "]" << endl); } catch(...) { - LOG->error() << "TafNodeFHelper::keepAlive unknown error" << endl; + TLOGERROR("[KeepAliveNodeFHelper::keepAlive unknown error]" << endl); } } -void TarsNodeFHelper::reportVersion(const string &version) +void KeepAliveNodeFHelper::reportVersion(const string &version) { - try - { + try + { if(_nodePrx) { _nodePrx->async_reportVersion(NULL, _si.application, _si.serverName, version); } - } - catch(exception &ex) - { - TLOGERROR("TarsNodeFHelper::reportVersion error:" << ex.what() << endl); - } - catch(...) - { - TLOGERROR("TarsNodeFHelper::reportVersion unknown error" << endl); - } + } + catch(exception &ex) + { + TLOGERROR("[KeepAliveNodeFHelper::reportVersion error:" << ex.what() << "]" << endl); + } + catch(...) + { + TLOGERROR("[KeepAliveNodeFHelper::reportVersion unknown error" << "]" << endl); + } } } diff --git a/servant/libservant/NetworkUtil.cpp b/servant/libservant/NetworkUtil.cpp index 67ab7418fb22ba03bf43a14c53dd2c8275232664..812b266265ebf16e362bba4c8d07e95da1ed7b10 100644 --- a/servant/libservant/NetworkUtil.cpp +++ b/servant/libservant/NetworkUtil.cpp @@ -42,6 +42,7 @@ int NetworkUtil::createSocket(bool udp, bool isLocal, bool isIpv6) { s.setTcpNoDelay(); s.setKeepAlive(); + s.setNoCloseWait(); } else { @@ -58,25 +59,6 @@ void NetworkUtil::closeSocketNoThrow(int fd) TC_Port::closeSocket(fd); } -//bool NetworkUtil::doConnect(int fd, const struct sockaddr& addr) -//{ -// bool bConnected = false; -// -// int iRet = ::connect(fd, (struct sockaddr*)(&addr), int(sizeof(addr))); -// -// if (iRet == 0) -// { -// bConnected = true; -// } -// else if (!TC_Socket::isInProgress()) -// { -// closeSocketNoThrow(fd); -// TARS_THROW_EXCEPTION_SYSCODE(TafNetConnectException, "NetworkUtil::doConnect error"); -// } -// -// return bConnected; -//} - bool NetworkUtil::doConnect(int fd, const struct sockaddr *addr, socklen_t len) { bool bConnected = false; @@ -90,7 +72,7 @@ bool NetworkUtil::doConnect(int fd, const struct sockaddr *addr, socklen_t len) else if (!TC_Socket::isInProgress()) { closeSocketNoThrow(fd); - TARS_THROW_EXCEPTION_SYSCODE(TarsNetConnectException, "NetworkUtil::doConnect error"); + THROW_EXCEPTION_SYSCODE(TarsNetConnectException, "NetworkUtil::doConnect error"); } return bConnected; diff --git a/servant/libservant/ObjectProxy.cpp b/servant/libservant/ObjectProxy.cpp index a4361476378857f704567ff1c0cc4c4ff4f3a953..f7f0b8e6a787c64613aae7443fbde2cd6503a47f 100755 --- a/servant/libservant/ObjectProxy.cpp +++ b/servant/libservant/ObjectProxy.cpp @@ -21,7 +21,7 @@ #include "servant/AppCache.h" #include "util/tc_common.h" #include "util/tc_clientsocket.h" -#include "servant/TarsLogger.h" +#include "servant/RemoteLogger.h" namespace tars { @@ -39,7 +39,8 @@ ObjectProxy::ObjectProxy(CommunicatorEpoll * pCommunicatorEpoll, const string & if(pos != string::npos) { - _name = sObjectProxyName.substr(0,pos); + _name = sObjectProxyName.substr(0,pos); + _address = sObjectProxyName.substr(pos+1); } else { @@ -53,9 +54,18 @@ ObjectProxy::ObjectProxy(CommunicatorEpoll * pCommunicatorEpoll, const string & } } - _proxyProtocol.requestFunc = ProxyProtocol::tarsRequest; + pos = _name.find_first_of('#'); + + if(pos != string::npos) + { + _hash = _name.substr(pos+1); + _name = _name.substr(0,pos); + } + + _proxyProtocol.requestFunc = ProxyProtocol::tarsRequest; _proxyProtocol.responseFunc = ProxyProtocol::tarsResponse; + _endpointManger.reset(new EndpointManager(this, _communicatorEpoll->getCommunicator(), sObjectProxyName, pCommunicatorEpoll->isFirstNetThread(), setName)); } @@ -67,16 +77,11 @@ ObjectProxy::~ObjectProxy() void ObjectProxy::initialize() { } -// -//ServantProxy * ObjectProxy::getServantProxy() -//{ -// return _pServantProxy; -//} -// -//void ObjectProxy::setServantProxy(ServantProxy * pServantProxy) -//{ -// _pServantProxy = pServantProxy; -//} + +const vector & ObjectProxy::getAdapters() +{ + return _endpointManger->getAdapters(); +} int ObjectProxy::loadLocator() { @@ -112,12 +117,6 @@ ServantProxyCallbackPtr ObjectProxy::getPushCallback() return _pushCallback; } -// -//const string& ObjectProxy::name() const -//{ -// return _name; -//} - void ObjectProxy::setProxyProtocol(const ProxyProtocol& protocol) { if(_hasSetProtocol) @@ -154,7 +153,7 @@ vector& ObjectProxy::getSocketOpt() // //bool ObjectProxy::invoke_sync(ReqMessage * msg) //{ -// TLOGTAF("[TAF][ObjectProxy::invoke_sync, " << _name << ", begin]" << endl); +// TLOGTARS("[ObjectProxy::invoke_sync, " << _name << ", begin]" << endl); // // //选择一个远程服务的Adapter来调用 // AdapterProxy * pAdapterProxy = NULL; @@ -172,7 +171,7 @@ vector& ObjectProxy::getSocketOpt() void ObjectProxy::invoke(ReqMessage * msg) { - TLOGTARS("[TARS][ObjectProxy::invoke, objname:" << _name << ", begin...]" << endl); + TLOGTARS("[ObjectProxy::invoke, objname:" << _name << ", begin...]" << endl); //选择一个远程服务的Adapter来调用 AdapterProxy * pAdapterProxy = NULL; @@ -186,14 +185,14 @@ void ObjectProxy::invoke(ReqMessage * msg) assert(bRet); //把数据缓存在obj里面 - TLOGTARS("[TARS][ObjectProxy::invoke, objname:" << _name << ", select adapter proxy not valid (have not inovoke reg)]" << endl); + TLOGTARS("[ObjectProxy::invoke, objname:" << _name << ", select adapter proxy not valid (have not invoke reg)]" << endl); return; } if(!pAdapterProxy) { - TLOGERROR("[TARS][ObjectProxy::invoke, objname:"<< _name << ", selectAdapterProxy is null]"<response->iRet = TARSADAPTERNULL; @@ -203,47 +202,111 @@ void ObjectProxy::invoke(ReqMessage * msg) } msg->adapter = pAdapterProxy; - pAdapterProxy->invoke(msg); -} -void ObjectProxy::doInvoke() -{ - TLOGTARS("[TARS][ObjectProxy::doInvoke, objname:" << _name << ", begin...]" << endl); - - while(!_reqTimeoutQueue.empty()) + //连接还没有建立, 暂时先放队列里面 + if(!msg->adapter->getTransceiver()->hasConnected()) { - TLOGTARS("[TARS][ObjectProxy::doInvoke, objname:" << _name << ", pop...]" << endl); + bool bRet = _reqTimeoutQueue.push(msg,msg->request.iTimeout+msg->iBeginTime); + + assert(bRet); - ReqMessage * msg = NULL; - _reqTimeoutQueue.pop(msg); + //把数据缓存在obj里面 + TLOGTARS("[ObjectProxy::invoke, " << _name << ", select adapter proxy not connected (have not inovoke reg)]" << endl); + return; + } - assert(msg != NULL); + pAdapterProxy->invoke(msg); +} - //选择一个远程服务的Adapter来调用 - AdapterProxy * pAdapterProxy = NULL; - _endpointManger->selectAdapterProxy(msg,pAdapterProxy, false); - if(!pAdapterProxy) - { - //这里肯定是请求过主控 - TLOGERROR("[TARS][ObjectProxy::doInvoke, objname:" << _name << ", selectAdapterProxy is null]" << endl); +void ObjectProxy::onConnect(AdapterProxy *adapterProxy) +{ + while(!_reqTimeoutQueue.empty()) + { + TLOGTARS("[ObjectProxy::onConnect, " << _name << ", queue size:" << _reqTimeoutQueue.size() << ", pop...]" << endl); + + ReqMessage * msg = NULL; + _reqTimeoutQueue.pop(msg); + + assert(msg != NULL); + + if(msg->adapter != NULL && msg->adapter != adapterProxy) + { + //选择一个远程服务的Adapter来调用 + _endpointManger->selectAdapterProxy(msg, adapterProxy, false); + + if (!adapterProxy) + { + //这里肯定是请求过主控 + TLOGERROR("[ObjectProxy::onConnect, " << _name << ", selectAdapterProxy is null]" << endl); + msg->response->iRet = TARSADAPTERNULL; + doInvokeException(msg); + return; + } + + msg->adapter = adapterProxy; + } + else + { + msg->adapter = adapterProxy; + } + + adapterProxy->invoke(msg); + } +} - msg->response->iRet = TARSADAPTERNULL; +void ObjectProxy::onNotifyEndpoints(const set & active,const set & inactive) +{ + if(_servantProxy) { + _servantProxy->onNotifyEndpoints(this->_communicatorEpoll->getCommunicatorEpollId(), active, inactive); + } +} - doInvokeException(msg); +void ObjectProxy::doInvoke() +{ + TLOGTARS("[ObjectProxy::doInvoke, objname:" << _name << ", begin...]" << endl); - return; - } + for(auto it = _reqTimeoutQueue.begin(); it != _reqTimeoutQueue.end(); ++it) + { + ReqMessage * msg = (*it).ptr; - msg->adapter = pAdapterProxy; + AdapterProxy* adapterProxy; - pAdapterProxy->invoke(msg); - } + //选择一个远程服务的Adapter来调用, selectAdapterProxy会发起连接 + _endpointManger->selectAdapterProxy(msg, adapterProxy, false); + } +// +// while(!_reqTimeoutQueue.empty()) +// { +// TLOGTARS("[ObjectProxy::doInvoke, " << _name << ", pop...]" << endl); +// +// ReqMessage * msg = NULL; +// _reqTimeoutQueue.pop(msg); +// +// assert(msg != NULL); +// +// AdapterProxy* adapterProxy; +// +// //选择一个远程服务的Adapter来调用 +// _endpointManger->selectAdapterProxy(msg, adapterProxy, false); +// +// if (!adapterProxy) { +// //这里肯定是请求过主控 +// TLOGERROR("[ObjectProxy::doInvoke, " << _name << ", selectAdapterProxy is null]" << endl); +// msg->response->iRet = JCEADAPTERNULL; +// doInvokeException(msg); +// return; +// } +// +// msg->adapter = adapterProxy; +// +// adapterProxy->invoke(msg); +// } } void ObjectProxy::doInvokeException(ReqMessage * msg) { - // TLOGTARS("[TARS][ObjectProxy::doInvokeException, objname:" << _name << "]" << endl); + // TLOGTARS("[ObjectProxy::doInvokeException, objname:" << _name << "]" << endl); //单向调用出现异常直接删除请求 if(msg->eType == ReqMessage::ONE_WAY) @@ -285,15 +348,15 @@ void ObjectProxy::doInvokeException(ReqMessage * msg) //比如获取endpoint try { - msg->callback->onDispatch(msgPtr); + msg->callback->dispatch(msgPtr); } catch(exception & e) { - TLOGERROR("[TARS]ObjectProxy::doInvokeException exp:" << e.what() << " ,line:" << __LINE__ << endl); + TLOGERROR("ObjectProxy::doInvokeException exp:" << e.what() << " ,line:" << __LINE__ << endl); } catch(...) { - TLOGERROR("[TARS]ObjectProxy::doInvokeException exp:unknown line:|" << __LINE__ << endl); + TLOGERROR("ObjectProxy::doInvokeException exp:unknown line:|" << __LINE__ << endl); } } else @@ -315,7 +378,7 @@ void ObjectProxy::doInvokeException(ReqMessage * msg) } else { - TLOGERROR("[TARS]ObjectProxy::doInvokeException coro parallel callback error, objname:" << _name << endl); + TLOGERROR("ObjectProxy::doInvokeException coro parallel callback error, objname:" << _name << endl); delete msg; } } @@ -334,7 +397,7 @@ void ObjectProxy::doTimeout() ReqMessage * reqInfo = NULL; while(_reqTimeoutQueue.timeout(reqInfo)) { - TLOGERROR("[TARS][ObjectProxy::doTimeout, objname:" << _name << ", queue timeout error]" << endl); + TLOGERROR("[ObjectProxy::doTimeout, objname:" << _name << ", queue timeout error]" << endl); reqInfo->response->iRet = TARSINVOKETIMEOUT; @@ -351,5 +414,16 @@ void ObjectProxy::mergeStat(map & mStatMicMsg) } } +void ObjectProxy::onSetInactive(const EndpointInfo& ep) +{ + const vector & vAdapterProxy = _endpointManger->getAdapters(); + for(size_t iAdapter=0; iAdapter< vAdapterProxy.size();++iAdapter) + { + if(vAdapterProxy[iAdapter]->endpoint() == ep) + { + vAdapterProxy[iAdapter]->onSetInactive(); + } + } +} //////////////////////////////////////////////////////////////////////////////////////////////// } diff --git a/servant/libservant/TarsConfig.cpp b/servant/libservant/RemoteConfig.cpp similarity index 85% rename from servant/libservant/TarsConfig.cpp rename to servant/libservant/RemoteConfig.cpp index a3b6f3104b0fe2a5100c953ad2ebda3da4666d72..6df07c256895f317903060a4330dd8c3d7350658 100755 --- a/servant/libservant/TarsConfig.cpp +++ b/servant/libservant/RemoteConfig.cpp @@ -14,16 +14,17 @@ * specific language governing permissions and limitations under the License. */ -#include "servant/TarsConfig.h" +#include "servant/RemoteConfig.h" #include "util/tc_file.h" #include "servant/Communicator.h" -#include "servant/TarsNotify.h" +#include "servant/RemoteNotify.h" +#include "servant/Application.h" #include namespace tars { -int TarsRemoteConfig::setConfigInfo(const CommunicatorPtr &comm, const string &obj, const string & app, const string &serverName, const string& basePath,const string& setdivision, int maxBakNum) +int RemoteConfig::setConfigInfo(const CommunicatorPtr &comm, const string &obj, const string & app, const string &serverName, const string& basePath,const string& setdivision, int maxBakNum) { _comm = comm; if(!obj.empty()) @@ -38,13 +39,13 @@ int TarsRemoteConfig::setConfigInfo(const CommunicatorPtr &comm, const string &o return 0; } -bool TarsRemoteConfig::addConfig(const string & sFileName, string &buffer, bool bAppConfigOnly) +bool RemoteConfig::addConfig(const string & sFileName, string &buffer, bool bAppConfigOnly) { TC_LockT lock(_mutex); try { - string sFullFileName = _basePath + "/" + sFileName; + string sFullFileName = _basePath + FILE_SEP + sFileName; string newFile = getRemoteFile(sFileName, bAppConfigOnly); @@ -96,7 +97,7 @@ bool TarsRemoteConfig::addConfig(const string & sFileName, string &buffer, bool return false; } -string TarsRemoteConfig::getRemoteFile(const string &sFileName, bool bAppConfigOnly) +string RemoteConfig::getRemoteFile(const string &sFileName, bool bAppConfigOnly) { if (_configPrx) { @@ -108,7 +109,7 @@ string TarsRemoteConfig::getRemoteFile(const string &sFileName, bool bAppConfigO { if(_setdivision.empty()) { - ret = _configPrx->loadConfig(_app, (bAppConfigOnly ? "" : _serverName), sFileName, stream); + ret = _configPrx->loadConfig(_app, (bAppConfigOnly ? "" : _serverName), sFileName, stream, ServerConfig::Context); } else { @@ -118,7 +119,7 @@ string TarsRemoteConfig::getRemoteFile(const string &sFileName, bool bAppConfigO confInfo.filename = sFileName; confInfo.bAppOnly = bAppConfigOnly; confInfo.setdivision = _setdivision; - ret = _configPrx->loadConfigByInfo(confInfo,stream); + ret = _configPrx->loadConfigByInfo(confInfo,stream, ServerConfig::Context); } break; @@ -148,7 +149,7 @@ string TarsRemoteConfig::getRemoteFile(const string &sFileName, bool bAppConfigO { out.close(); result = "[fail] copy stream to disk error." ; - TarsRemoteNotify::getInstance()->report(result); + RemoteNotify::getInstance()->report(result); return ""; } else @@ -161,19 +162,19 @@ string TarsRemoteConfig::getRemoteFile(const string &sFileName, bool bAppConfigO return ""; } -string TarsRemoteConfig::index2file(const string & sFullFileName, int index) +string RemoteConfig::index2file(const string & sFullFileName, int index) { return sFullFileName + "." + TC_Common::tostr(index) + ".bak"; } -void TarsRemoteConfig::localRename(const string& oldFile, const string& newFile) +void RemoteConfig::localRename(const string& oldFile, const string& newFile) { -#if TARGET_PLATFORM_WINDOWS - //by goodenpei,windows下面先remove后rename,否则rename会失败 - if (TC_File::isFileExist(oldFile) && TC_File::isFileExist(newFile)) - { - ::remove(newFile.c_str()); - } +#if TARGET_PLATFORM_WINDOWS + //by goodenpei,windows下面先remove后rename,否则rename会失败 + if (TC_File::isFileExist(oldFile) && TC_File::isFileExist(newFile)) + { + ::remove(newFile.c_str()); + } #endif if (::rename(oldFile.c_str(), newFile.c_str()) != 0) { @@ -181,7 +182,7 @@ void TarsRemoteConfig::localRename(const string& oldFile, const string& newFile) } } -string TarsRemoteConfig::recoverSysConfig(const string & sFullFileName) +string RemoteConfig::recoverSysConfig(const string & sFullFileName) { try { diff --git a/servant/libservant/TarsLogger.cpp b/servant/libservant/RemoteLogger.cpp similarity index 85% rename from servant/libservant/TarsLogger.cpp rename to servant/libservant/RemoteLogger.cpp index 41a8454cc135f9e41dddd3c4e0803554ef159d00..321f8702b6e8296f928de22f7724436da791bf9b 100644 --- a/servant/libservant/TarsLogger.cpp +++ b/servant/libservant/RemoteLogger.cpp @@ -14,7 +14,7 @@ * specific language governing permissions and limitations under the License. */ -#include "servant/TarsLogger.h" +#include "servant/RemoteLogger.h" #include "servant/Communicator.h" #include "servant/Application.h" @@ -84,11 +84,11 @@ void RollWriteT::operator()(ostream &of, const deque > &ds) { try { - _logPrx->logger(DYEING_DIR, DYEING_FILE, "roll", "%Y%m%d", vRemoteDyeing); + _logPrx->logger(DYEING_DIR, DYEING_FILE, "roll", "%Y%m%d", vRemoteDyeing, ServerConfig::Context); } catch(exception &ex) { - TLOGERROR("[TARS] dyeing log write to remote log server error:" << ex.what() << endl); + TLOGERROR("[dyeing log write to remote log server error:" << ex.what() << "]" << endl); } } } @@ -112,7 +112,7 @@ void RollWriteT::setDyeingLogInfo(const string &sApp, const string &sServer, con ///////////////////////////////////////////////////////////////////////////////////// -void TarsRollLogger::setLogInfo(const string &sApp, const string &sServer, const string &sLogpath, int iMaxSize, int iMaxNum, const CommunicatorPtr &comm, const string &sLogObj) +void LocalRollLogger::setLogInfo(const string &sApp, const string &sServer, const string &sLogpath, int iMaxSize, int iMaxNum, const CommunicatorPtr &comm, const string &sLogObj) { _app = sApp; _server = sServer; @@ -138,7 +138,7 @@ void TarsRollLogger::setLogInfo(const string &sApp, const string &sServer, const } -void TarsRollLogger::sync(bool bSync) +void LocalRollLogger::sync(bool bSync) { if(bSync) { @@ -150,7 +150,7 @@ void TarsRollLogger::sync(bool bSync) } } -void TarsRollLogger::enableDyeing(bool bEnable, const string& sDyeingKey/* = ""*/) +void LocalRollLogger::enableDyeing(bool bEnable, const string& sDyeingKey/* = ""*/) { _logger.getRoll()->enableDyeing(bEnable, sDyeingKey); } @@ -254,7 +254,7 @@ void RemoteTimeWriteT::sync2remote(const vector &v) stInfo.sSepar = _timeWrite->_separ; stInfo.sLogType = _timeWrite->_logType; - _timeWrite->_logPrx->loggerbyInfo(stInfo,v); + _timeWrite->_logPrx->loggerbyInfo(stInfo,v, ServerConfig::Context); if (_timeWrite->_reportSuccPtr) { @@ -263,7 +263,7 @@ void RemoteTimeWriteT::sync2remote(const vector &v) } catch(exception &ex) { - TLOGERROR("[TARS] write to remote log server error:" << ex.what() << ": buffer size:" << v.size() << endl); + TLOGERROR("[write to remote log server error:" << ex.what() << ": buffer size:" << v.size() << "]"<< endl); _timeWrite->writeError(v); if (_timeWrite->_reportFailPtr) { @@ -276,11 +276,11 @@ void RemoteTimeWriteT::sync2remoteDyeing(const vector &v) { try { - _timeWrite->_logPrx->logger(DYEING_DIR, DYEING_FILE, "", _timeWrite->_format, v); + _timeWrite->_logPrx->logger(DYEING_DIR, DYEING_FILE, "", _timeWrite->_format, v, ServerConfig::Context); } catch(exception &ex) { - TLOGERROR("[TARS] write dyeing log to remote log server error:" << ex.what() << ": buffer size:" << v.size() << endl); + TLOGERROR("[write dyeing log to remote log server error:" << ex.what() << ": buffer size:" << v.size() << "]" << endl); _timeWrite->writeError(v); } } @@ -418,11 +418,11 @@ void TimeWriteT::operator()(ostream &of, const deque > &buf { try { - _logPrx->logger(DYEING_DIR, DYEING_FILE, "day", "%Y%m%d", vDyeingLog); + _logPrx->logger(DYEING_DIR, DYEING_FILE, "day", "%Y%m%d", vDyeingLog, ServerConfig::Context); } catch(exception &ex) { - TLOGERROR("[TARS] dyeing log write to remote log server error:" << ex.what() << endl); + TLOGERROR("[dyeing log write to remote log server error:" << ex.what() << "]" << endl); } } } @@ -437,10 +437,10 @@ void TimeWriteT::writeError(const vector &buffer) } } - //告警 - string sInfo = _app + "." + _server + "|"; - sInfo += ServerConfig::LocalIp + "|sync log to remote tarslog error"; - FDLOG("tarserror") << sInfo < > &buffer) } } - //告警 - string sInfo = _app + "." + _server + "|"; - sInfo += ServerConfig::LocalIp + "|sync log to remote tarslog error(buffer.size>500000)"; - FDLOG("tarserror") << sInfo <500000)"; + // FDLOG("tarserror") << sInfo <getWriteT().setLogInfo(_logPrx, _app, _server, sFile, _logpath, sFormat, _setDivision, sLogType, reportSuccPtr, reportFailPtr); } -void TarsTimeLogger::initTimeLogger(TimeLogger *pTimeLogger,const string &sApp, const string &sServer, const string &sFile, const string &sFormat,const TarsLogTypePtr& logTypePtr) +void RemoteTimeLogger::initTimeLogger(TimeLogger *pTimeLogger,const string &sApp, const string &sServer, const string &sFile, const string &sFormat,const LogTypePtr& logTypePtr) { string sAppSrvName = _hasAppNamePrefix?(sApp + "." + sServer):""; string sFilePath = _logpath + "/" + sApp + "/" + sServer + "/" + sAppSrvName; @@ -576,7 +576,7 @@ void TarsTimeLogger::initTimeLogger(TimeLogger *pTimeLogger,const string &sApp, pTimeLogger->getWriteT().setLogInfo(_logPrx, sApp, sServer, sFile, _logpath, sFormat, _setDivision, sLogType, reportSuccPtr, reportFailPtr); } -void TarsTimeLogger::setLogInfo(const CommunicatorPtr &comm, const string &obj, const string &sApp, const string &sServer, const string &sLogpath, const string& setdivision, const bool &bLogStatReport) +void RemoteTimeLogger::setLogInfo(const CommunicatorPtr &comm, const string &obj, const string &sApp, const string &sServer, const string &sLogpath, const string& setdivision, const bool &bLogStatReport) { _app = sApp; _server = sServer; @@ -600,7 +600,7 @@ void TarsTimeLogger::setLogInfo(const CommunicatorPtr &comm, const string &obj, TC_File::makeDirRecursive(_logpath + "/" + _app + "/" + _server); } -void TarsTimeLogger::initFormat(const string &sFile, const string &sFormat,const TarsLogTypePtr& logTypePtr) +void RemoteTimeLogger::initFormat(const string &sFile, const string &sFormat,const LogTypePtr& logTypePtr) { if(sFile.empty()) { @@ -627,7 +627,7 @@ void TarsTimeLogger::initFormat(const string &sFile, const string &sFormat,const initTimeLogger(it->second, sFile, sFormat,logTypePtr); } } -void TarsTimeLogger::initFormat(const string &sApp, const string &sServer,const string &sFile, const string &sFormat,const TarsLogTypePtr& logTypePtr) +void RemoteTimeLogger::initFormat(const string &sApp, const string &sServer,const string &sFile, const string &sFormat,const LogTypePtr& logTypePtr) { string s = sApp + "/" + sServer + "/"+ sFile; Lock lock(*this); @@ -643,7 +643,7 @@ void TarsTimeLogger::initFormat(const string &sApp, const string &sServer,const initTimeLogger(it->second, sApp, sServer, sFile, sFormat,logTypePtr); } -TarsTimeLogger::TimeLogger* TarsTimeLogger::logger(const string &sFile) +RemoteTimeLogger::TimeLogger* RemoteTimeLogger::logger(const string &sFile) { if(sFile.empty()) { @@ -669,7 +669,7 @@ TarsTimeLogger::TimeLogger* TarsTimeLogger::logger(const string &sFile) return it->second; } -TarsTimeLogger::TimeLogger* TarsTimeLogger::logger(const string &sApp, const string &sServer,const string &sFile) +RemoteTimeLogger::TimeLogger* RemoteTimeLogger::logger(const string &sApp, const string &sServer,const string &sFile) { string s = sApp + "/" + sServer + "/"+ sFile; @@ -687,7 +687,7 @@ TarsTimeLogger::TimeLogger* TarsTimeLogger::logger(const string &sApp, const str } -void TarsTimeLogger::sync(const string &sFile, bool bSync) +void RemoteTimeLogger::sync(const string &sFile, bool bSync) { if(bSync) { @@ -699,22 +699,22 @@ void TarsTimeLogger::sync(const string &sFile, bool bSync) } } -void TarsTimeLogger::enableRemote(const string &sFile, bool bEnable) +void RemoteTimeLogger::enableRemote(const string &sFile, bool bEnable) { logger(sFile)->getWriteT().enableRemote(bEnable); } -void TarsTimeLogger::enableRemoteEx(const string &sApp, const string &sServer,const string &sFile, bool bEnable) +void RemoteTimeLogger::enableRemoteEx(const string &sApp, const string &sServer,const string &sFile, bool bEnable) { logger(sApp,sServer,sFile)->getWriteT().enableRemote(bEnable); } -void TarsTimeLogger::enableLocal(const string &sFile, bool bEnable) +void RemoteTimeLogger::enableLocal(const string &sFile, bool bEnable) { logger(sFile)->getWriteT().enableLocal(bEnable); logger(sFile)->setRemote(!bEnable); } -void TarsTimeLogger::enableLocalEx(const string &sApp, const string &sServer,const string &sFile, bool bEnable) +void RemoteTimeLogger::enableLocalEx(const string &sApp, const string &sServer,const string &sFile, bool bEnable) { logger(sApp,sServer,sFile)->getWriteT().enableLocal(bEnable); logger(sApp,sServer,sFile)->setRemote(!bEnable); diff --git a/servant/libservant/TarsNotify.cpp b/servant/libservant/RemoteNotify.cpp similarity index 66% rename from servant/libservant/TarsNotify.cpp rename to servant/libservant/RemoteNotify.cpp index bb267a630a35d589a878cc277d78bf15aa789f4c..d252d0175e6301e45d8b2270e84260f592b5a377 100644 --- a/servant/libservant/TarsNotify.cpp +++ b/servant/libservant/RemoteNotify.cpp @@ -14,14 +14,14 @@ * specific language governing permissions and limitations under the License. */ -#include "servant/TarsNotify.h" +#include "servant/RemoteNotify.h" #include "servant/Communicator.h" -#include "servant/TarsLogger.h" +#include "servant/RemoteLogger.h" namespace tars { -int TarsRemoteNotify::setNotifyInfo(const CommunicatorPtr &comm, const string &obj, const string & app, const string &serverName, const string &sSetName, const string &nodeName) +int RemoteNotify::setNotifyInfo(const CommunicatorPtr &comm, const string &obj, const string & app, const string &serverName, const string &sSetName, const string &nodeName) { _comm = comm; if(!obj.empty()) @@ -37,13 +37,14 @@ int TarsRemoteNotify::setNotifyInfo(const CommunicatorPtr &comm, const string &o return 0; } -void TarsRemoteNotify::report(const string &sResult, bool bSync) +void RemoteNotify::report(const string &sResult, bool bSync) { try { if(_notifyPrx) { ReportInfo info; + info.eType = REPORT; info.sApp = _app; info.sServer = _serverName; info.sSet = _setName; @@ -52,34 +53,32 @@ void TarsRemoteNotify::report(const string &sResult, bool bSync) info.sNodeName = _nodeName; if(!bSync) { - //_notifyPrx->async_reportServer(NULL, _app + "." + _serverName, TC_Common::tostr(std::this_thread::get_id()), sResult); _notifyPrx->async_reportNotifyInfo(NULL, info); } else { - //_notifyPrx->reportServer(_app + "." + _serverName, TC_Common::tostr(std::this_thread::get_id()), sResult); _notifyPrx->reportNotifyInfo(info); } } } catch(exception &ex) { - TLOGERROR("TarsRemoteNotify::report error:" << ex.what() << endl); + TLOGERROR("[RemoteNotify::report error:" << ex.what() << "]" << endl); } catch(...) { - TLOGERROR("TarsRemoteNotify::report unknown error" << endl); + TLOGERROR("[RemoteNotify::report unknown error" << "]" << endl); } } -void TarsRemoteNotify::notify(NOTIFYLEVEL level, const string &sMessage) +void RemoteNotify::notify(NOTIFYLEVEL level, const string &sMessage) { try { if(_notifyPrx) { ReportInfo info; - // info.eType = 0; + info.eType = NOTIFY; info.sApp = _app; info.sServer = _serverName; info.sSet = _setName; @@ -87,28 +86,27 @@ void TarsRemoteNotify::notify(NOTIFYLEVEL level, const string &sMessage) info.sMessage = sMessage; info.eLevel = level; info.sNodeName = _nodeName; - //_notifyPrx->async_notifyServer(NULL, _app + "." + _serverName, level, sMessage); _notifyPrx->async_reportNotifyInfo(NULL, info); } } catch(exception &ex) { - TLOGERROR("TarsRemoteNotify::notify error:" << ex.what() << endl); + TLOGERROR("[RemoteNotify::notify error:" << ex.what() << "]" << endl); } catch(...) { - TLOGERROR("TarsRemoteNotify::notify unknown error" << endl); + TLOGERROR("[RemoteNotify::notify unknown error" << "]" << endl); } } -void TarsRemoteNotify::report(const string &sMessage, const string & app, const string &serverName, const string &sNodeName) +void RemoteNotify::report(const string &sMessage, const string & app, const string &serverName, const string &sNodeName) { try { if(_notifyPrx) { ReportInfo info; - // info.eType = 0; + info.eType = REPORT; info.sApp = app; info.sServer = serverName; info.sSet = ""; @@ -119,11 +117,11 @@ void TarsRemoteNotify::report(const string &sMessage, const string & app, const } catch(exception &ex) { - TLOGERROR("TarsRemoteNotify::notify error:" << ex.what() << endl); + TLOGERROR("[RemoteNotify::notify error:" << ex.what() << "]" << endl); } catch(...) { - TLOGERROR("TarsRemoteNotify::notify unknown error" << endl); + TLOGERROR("[RemoteNotify::notify unknown error" << "]" << endl); } } diff --git a/servant/libservant/Servant.cpp b/servant/libservant/Servant.cpp index ef986b776ef60ca701251ed79558708cfb6e08b1..fe38028a433589638e4e6edf2ca7bf6383841a70 100644 --- a/servant/libservant/Servant.cpp +++ b/servant/libservant/Servant.cpp @@ -18,7 +18,7 @@ #include "servant/BaseF.h" #include "servant/Application.h" #include "servant/AppCache.h" -#include "servant/TarsLogger.h" +#include "servant/RemoteLogger.h" #include @@ -71,7 +71,7 @@ int Servant::dispatch(TarsCurrentPtr current, vector &buffer) if (current->getFuncName() == "tars_ping") { - TLOGTARS("[TARS][Servant::dispatch] tars_ping ok from [" << current->getIp() << ":" << current->getPort() << "]" << endl); + TLOGTARS("[Servant::dispatch] tars_ping ok from [" << current->getIp() << ":" << current->getPort() << "]" << endl); ret = TARSSERVERSUCCESS; } diff --git a/servant/libservant/ServantHandle.cpp b/servant/libservant/ServantHandle.cpp index b07f3ec1df96ba4c67979852e87b1a8a79f6d3eb..0b0d829a8ebb4a005558dec4c98338d265fc604c 100644 --- a/servant/libservant/ServantHandle.cpp +++ b/servant/libservant/ServantHandle.cpp @@ -21,8 +21,9 @@ #include "servant/ServantHelper.h" #include "servant/AppProtocol.h" #include "servant/BaseF.h" -#include "servant/TarsNodeF.h" -#ifdef _USE_OPENTRACKING +#include "servant/KeepAliveNodeF.h" +#include "servant/Cookie.h" +#ifdef TARS_OPENTRACKING #include "servant/text_map_carrier.h" #endif @@ -49,11 +50,11 @@ ServantHandle::~ServantHandle() } catch(exception &ex) { - TLOGERROR("[TARS]ServantHandle::destroy error:" << ex.what() << endl); + TLOGERROR("[ServantHandle::destroy error:" << ex.what() << "]" << endl); } catch(...) { - TLOGERROR("[TARS]ServantHandle::destroy unknown exception error" << endl); + TLOGERROR("[ServantHandle::destroy unknown exception error]" << endl); } ++it; } @@ -113,13 +114,13 @@ void ServantHandle::run() } catch(exception &ex) { - TLOGERROR("[TARS]ServantHandle::run exception error:" << ex.what() << endl); - cerr << "[TARS]ServantHandle::run exception error:" << ex.what() << endl; + TLOGERROR("[ServantHandle::run exception error:" << ex.what() << "]" << endl); + cerr << "ServantHandle::run exception error:" << ex.what() << endl; } catch(...) { - TLOGERROR("[TARS]ServantHandle::run unknown exception error." << endl); - cerr << "[TARS]ServantHandle::run unknown exception error." << endl; + TLOGERROR("[ServantHandle::run unknown exception error]" << endl); + cerr << "ServantHandle::run unknown exception error]" << endl; } } @@ -240,11 +241,11 @@ void ServantHandle::handleRecvData(const shared_ptr } catch(exception &ex) { - TLOGERROR("[TARS]ServantHandle::handleRecvData exception:" << ex.what() << endl); + TLOGERROR("[ServantHandle::handleRecvData exception:" << ex.what() << "]" << endl); } catch(...) { - TLOGERROR("[TARS]ServantHandle::handleRecvData unknown exception error" << endl); + TLOGERROR("[ServantHandle::handleRecvData unknown exception error]" << endl); } } @@ -275,11 +276,11 @@ void ServantHandle::handleAsyncResponse() } catch (exception& e) { - TLOGERROR("[TARS][ServantHandle::doResponse ex:" << e.what() << "]" << endl); + TLOGERROR("[ServantHandle::doResponse ex:" << e.what() << "]" << endl); } catch (...) { - TLOGERROR("[TARS][ServantHandle::doResponse ex.]" << endl); + TLOGERROR("[ServantHandle::doResponse error]" << endl); } } @@ -291,11 +292,11 @@ void ServantHandle::handleAsyncResponse() } catch (exception& e) { - TLOGERROR("[TARS][ServantHandle::doCustemMessage ex:" << e.what() << "]" << endl); + TLOGERROR("[ServantHandle::doCustemMessage ex:" << e.what() << "]" << endl); } catch (...) { - TLOGERROR("[TARS][ServantHandle::doCustemMessage ex.]" << endl); + TLOGERROR("[ServantHandle::doCustemMessage ex.]" << endl); } ++it; @@ -314,11 +315,11 @@ void ServantHandle::handleCustomMessage(bool bExpectIdle) } catch (exception& e) { - TLOGERROR("[TARS][ServantHandle::doCustemMessage ex:" << e.what() << "]" << endl); + TLOGERROR("[ServantHandle::doCustemMessage ex:" << e.what() << "]" << endl); } catch (...) { - TLOGERROR("[TARS][ServantHandle::doCustemMessage ex.]" << endl); + TLOGERROR("[ServantHandle::doCustemMessage ex.]" << endl); } } } @@ -348,8 +349,13 @@ void ServantHandle::initialize() } else { - TLOGERROR("[TAF]ServantHandle initialize createServant ret null, for adapter `" +_bindAdapter->getName() + "`" << endl); - cerr << "[TAF]ServantHandle initialize createServant ret null, for adapter `" +_bindAdapter->getName() + "`" << endl; + TLOGERROR("[ServantHandle initialize createServant ret null, for adapter `" +_bindAdapter->getName() + "`]" << endl); + cerr << "ServantHandle initialize createServant ret null, for adapter `" +_bindAdapter->getName() + "`]" << endl; + + RemoteNotify::getInstance()->report("initialize createServant error: no adapter:" + _bindAdapter->getName()); + + TC_Common::msleep(100); + exit(-1); } @@ -357,9 +363,11 @@ void ServantHandle::initialize() if(it == _servants.end()) { - TLOGERROR("[TARS]initialize error: no servant exists." << endl); + TLOGERROR("[initialize error: no servant exists]" << endl); - TarsRemoteNotify::getInstance()->report("initialize error: no servant exists."); + RemoteNotify::getInstance()->report("initialize error: no servant exists."); + + TC_Common::msleep(100); exit(-1); } @@ -372,23 +380,27 @@ void ServantHandle::initialize() it->second->initialize(); - TLOGTARS("[TARS][" << it->second->getName() << "] initialize" << endl); + TLOGTARS("[" << it->second->getName() << " initialize]" << endl); } catch(exception &ex) { - TLOGERROR("[TARS]initialize error:" << ex.what() << endl); + TLOGERROR("[initialize error:" << ex.what() << "]" << endl); + + RemoteNotify::getInstance()->report("initialize error:" + string(ex.what())); - TarsRemoteNotify::getInstance()->report("initialize error:" + string(ex.what())); + TC_Common::msleep(100); - exit(-1); + exit(-1); } catch(...) { - TLOGERROR("[TARS]initialize unknown exception error" << endl); + TLOGERROR("[initialize unknown exception error]" << endl); + + RemoteNotify::getInstance()->report("initialize unknown exception error"); - TarsRemoteNotify::getInstance()->report("initialize error"); + TC_Common::msleep(100); - exit(-1); + exit(-1); } ++it; } @@ -404,7 +416,7 @@ void ServantHandle::heartbeat() TARS_KEEPALIVE(_bindAdapter->getName()); - //上报连接数 比率 + //上报连接数 比率 if (_bindAdapter->_pReportConRate) { _bindAdapter->_pReportConRate->report((int)(_bindAdapter->getNowConnection() * 1000 / _bindAdapter->getMaxConns())); @@ -420,7 +432,7 @@ void ServantHandle::heartbeat() TarsCurrentPtr ServantHandle::createCurrent(const shared_ptr &data) { - TarsCurrentPtr current = new TarsCurrent(this); + TarsCurrentPtr current = new Current(this); try { @@ -428,7 +440,7 @@ TarsCurrentPtr ServantHandle::createCurrent(const shared_ptradapter()->_pReportTimeoutNum) data->adapter()->_pReportTimeoutNum->report(1); - TLOGERROR("[TARS]ServantHandle::handle queue timeout:" - << current->_request.sServantName << "|" - << current->_request.sFuncName << "|" - << data->recvTimeStamp() << "|" - << data->adapter()->getQueueTimeout() << "|" - << current->_request.iTimeout << "|" - << now << "|" << data->ip() << ":" << data->port() << endl); + TLOGERROR("[ServantHandle::handle queue timeout:" + << current->_request.sServantName << ", func:" + << current->_request.sFuncName << ", recv time:" + << data->recvTimeStamp() << ", queue timeout:" + << data->adapter()->getQueueTimeout() << ", timeout:" + << current->_request.iTimeout << ", now:" + << now << ", ip:" << data->ip() << ", port:" << data->port() << "]" << endl); current->sendResponse(TARSSERVERQUEUETIMEOUT); @@ -464,7 +476,7 @@ TarsCurrentPtr ServantHandle::createCurrent(const shared_ptr &data) { - TarsCurrentPtr current = new TarsCurrent(this); + TarsCurrentPtr current = new Current(this); current->initializeClose(data); current->setReportStat(false); @@ -474,8 +486,7 @@ TarsCurrentPtr ServantHandle::createCloseCurrent(const shared_ptr &data) { - TLOGTARS("[TARS]ServantHandle::handleClose,adapter:" << data->adapter()->getName() - << ",peer:" << data->ip() << ":" << data->port() << endl); + TLOGTARS("[ServantHandle::handleClose,adapter:" << data->adapter()->getName() << ",peer:" << data->ip() << ":" << data->port() << "]"<< endl); TarsCurrentPtr current = createCloseCurrent(data); @@ -483,8 +494,8 @@ void ServantHandle::handleClose(const shared_ptr &d if (sit == _servants.end()) { - TLOGERROR("[TARS]ServantHandle::handleClose,adapter:" << data->adapter()->getName() - << ",peer:" << data->ip() << ":" << data->port()<<", " << current->getServantName() << " not found" << endl); + TLOGERROR("[ServantHandle::handleClose,adapter:" << data->adapter()->getName() + << ",peer:" << data->ip() << ":" << data->port()<<", " << current->getServantName() << " not found]" << endl); return; } @@ -497,13 +508,13 @@ void ServantHandle::handleClose(const shared_ptr &d } catch(exception &ex) { - TLOGERROR("[TARS]ServantHandle::handleClose " << ex.what() << endl); + TLOGERROR("[ServantHandle::handleClose " << ex.what() << "]" << endl); return; } catch(...) { - TLOGERROR("[TARS]ServantHandle::handleClose unknown error" << endl); + TLOGERROR("[ServantHandle::handleClose unknown error]" << endl); return; } @@ -519,11 +530,11 @@ void ServantHandle::handleTimeout(const shared_ptr if(data->adapter()->_pReportTimeoutNum) data->adapter()->_pReportTimeoutNum->report(1); - TLOGERROR("[TARS]ServantHandle::handleTimeout adapter '" + TLOGERROR("[ServantHandle::handleTimeout adapter '" << data->adapter()->getName() << "', recvtime:" << data->recvTimeStamp() << "|" << ", timeout:" << data->adapter()->getQueueTimeout() - << ", id:" << current->getRequestId() << endl); + << ", id:" << current->getRequestId() << "]" << endl); if (current->getBindAdapter()->isTarsProtocol()) { @@ -537,11 +548,11 @@ void ServantHandle::handleOverload(const shared_ptr if (!current) return; - TLOGERROR("[TARS]ServantHandle::handleOverload adapter '" + TLOGERROR("[ServantHandle::handleOverload adapter '" << data->adapter()->getName() << "',overload:-1,queue capacity:" << data->adapter()->getQueueCapacity() - << ",id:" << current->getRequestId() << endl); + << ",id:" << current->getRequestId() << "]" << endl); if (current->getBindAdapter()->isTarsProtocol()) { @@ -566,7 +577,7 @@ void ServantHandle::handle(const shared_ptr &data) } -#ifdef _USE_OPENTRACKING +#ifdef TARS_OPENTRACKING void ServantHandle::processTracking(const TarsCurrentPtr ¤t) { if(!(Application::getCommunicator()->_traceManager)) @@ -661,34 +672,33 @@ bool ServantHandle::processDye(const TarsCurrentPtr ¤t, string& dyeingKey) if (IS_MSG_TYPE(current->getMessageType(), tars::TARSMESSAGETYPEDYED)) { - TLOGTARS("[TARS] servant got a dyeing request, message_type set" << current->getMessageType() << endl); + TLOGTARS("[servant got a dyeing request, message_type set: " << current->getMessageType() << "]" << endl); if (dyeingIt != current->getRequestStatus().end()) { - TLOGTARS("[TARS] servant got a dyeing request, dyeing key:" << dyeingIt->second << endl); + TLOGTARS("[servant got a dyeing request, dyeing key: " << dyeingIt->second << "]" << endl); dyeingKey = dyeingIt->second; } return true; } - //servant已经被染色, 开启染色日志 - if (ServantHelperManager::getInstance()->isDyeing()) - { - map::const_iterator dyeingKeyIt = current->getRequestStatus().find(ServantProxy::STATUS_GRID_KEY); + return false; +} - if (dyeingKeyIt != current->getRequestStatus().end() && - ServantHelperManager::getInstance()->isDyeingReq(dyeingKeyIt->second, current->getServantName(), current->getFuncName())) - { - TLOGTARS("[TARS] dyeing servant got a dyeing req, key:" << dyeingKeyIt->second << endl); - dyeingKey = dyeingKeyIt->second; +bool ServantHandle::processCookie(const TarsCurrentPtr ¤t, map &cookie) +{ + const static string STATUS = "STATUS_"; - return true; - } - } + std::for_each(current->getRequestStatus().begin(), current->getRequestStatus().end(),[&](const map::value_type& p){ + if(p.first.size() > STATUS.size() && TC_Port::strncasecmp(p.first.c_str(), STATUS.c_str(), STATUS.size()) == 0) { + return; + } + cookie.insert(make_pair(p.first, p.second)); + }); - return false; + return !cookie.empty(); } bool ServantHandle::checkValidSetInvoke(const TarsCurrentPtr ¤t) @@ -716,7 +726,7 @@ bool ServantHandle::checkValidSetInvoke(const TarsCurrentPtr ¤t) if (setIt != current->getRequestStatus().end()) { - TLOGTARS("[TARS] servant got a setname request, setname key:" << setIt->second << endl); + TLOGTARS("[servant got a setname request, setname key:" << setIt->second << "]" << endl); sSetName = setIt->second; @@ -741,13 +751,13 @@ bool ServantHandle::checkValidSetInvoke(const TarsCurrentPtr ¤t) } else { - TLOGERROR("[TARS]ServantHandle::checkValidSetInvoke|" + TLOGERROR("[ServantHandle::checkValidSetInvoke|" << current->getIp() << "|" << current->getMessageType() << "|" << current->getServantName() << "|" << current->getFuncName() << "|client:" << ClientConfig::SetDivision << "|server:" - << sSetName << endl); + << sSetName << "]" << endl); current->sendResponse(TARSINVOKEBYINVALIDESET); return false; } @@ -755,13 +765,13 @@ bool ServantHandle::checkValidSetInvoke(const TarsCurrentPtr ¤t) } else { - TLOGERROR("[TARS]ServantHandle::checkValidSetInvoke|" + TLOGERROR("[ServantHandle::checkValidSetInvoke|" << current->getIp() << "|" << current->getMessageType() << "|" << current->getServantName() << "|" << current->getFuncName() << "|client:" << ClientConfig::SetDivision << "|server:" - << sSetName << endl); + << sSetName << "]" << endl); current->sendResponse(TARSINVOKEBYINVALIDESET); return false; } @@ -773,14 +783,14 @@ bool ServantHandle::checkValidSetInvoke(const TarsCurrentPtr ¤t) void ServantHandle::handleTarsProtocol(const TarsCurrentPtr ¤t) { - TLOGTARS("[TARS]ServantHandle::handleTarsProtocol current:" + TLOGTARS("[ServantHandle::handleTarsProtocol current:" << current->getIp() << "|" << current->getPort() << "|" << current->getMessageType() << "|" << current->getServantName() << "|" << current->getFuncName() << "|" << current->getRequestId() << "|" - << TC_Common::tostr(current->getRequestStatus())<getRequestStatus()) << "]"< cookie; + CookieOp cookieOp; + if (processCookie(current, cookie)) + { + cookieOp.setCookie(cookie); + current->setCookie(cookie); + } + +#ifdef TARS_OPENTRACKING //处理tracking信息 processTracking(current); #endif @@ -805,7 +824,7 @@ void ServantHandle::handleTarsProtocol(const TarsCurrentPtr ¤t) if (sit == _servants.end()) { current->sendResponse(TARSSERVERNOSERVANTERR); -#ifdef _USE_OPENTRACKING +#ifdef TARS_OPENTRACKING finishTracking(TARSSERVERNOSERVANTERR, current); #endif return; @@ -823,7 +842,7 @@ void ServantHandle::handleTarsProtocol(const TarsCurrentPtr ¤t) } catch(TarsDecodeException &ex) { - TLOGERROR("[TARS]ServantHandle::handleTarsProtocol " << ex.what() << endl); + TLOGERROR("[ServantHandle::handleTarsProtocol " << ex.what() << "]" << endl); ret = TARSSERVERDECODEERR; @@ -831,7 +850,7 @@ void ServantHandle::handleTarsProtocol(const TarsCurrentPtr ¤t) } catch(TarsEncodeException &ex) { - TLOGERROR("[TARS]ServantHandle::handleTarsProtocol " << ex.what() << endl); + TLOGERROR("[ServantHandle::handleTarsProtocol " << ex.what() << "]" << endl); ret = TARSSERVERENCODEERR; @@ -839,7 +858,7 @@ void ServantHandle::handleTarsProtocol(const TarsCurrentPtr ¤t) } catch(exception &ex) { - TLOGERROR("[TARS]ServantHandle::handleTarsProtocol " << ex.what() << endl); + TLOGERROR("[ServantHandle::handleTarsProtocol " << ex.what() << "]" << endl); ret = TARSSERVERUNKNOWNERR; @@ -847,7 +866,7 @@ void ServantHandle::handleTarsProtocol(const TarsCurrentPtr ¤t) } catch(...) { - TLOGERROR("[TARS]ServantHandle::handleTarsProtocol unknown error" << endl); + TLOGERROR("[ServantHandle::handleTarsProtocol unknown error]" << endl); ret = TARSSERVERUNKNOWNERR; @@ -857,19 +876,19 @@ void ServantHandle::handleTarsProtocol(const TarsCurrentPtr ¤t) //单向调用或者业务不需要同步返回 if (current->isResponse()) { - current->sendResponse(ret, buffer, TarsCurrent::TARS_STATUS(), sResultDesc); + current->sendResponse(ret, buffer, Current::TARS_STATUS(), sResultDesc); } -#ifdef _USE_OPENTRACKING +#ifdef TARS_OPENTRACKING finishTracking(ret, current); #endif } void ServantHandle::handleNoTarsProtocol(const TarsCurrentPtr ¤t) { - TLOGTARS("[TARS]ServantHandle::handleNoTarsProtocol current:" + TLOGTARS("[ServantHandle::handleNoTarsProtocol current:" << current->getIp() << "|" << current->getPort() << "|" - << current->getServantName() << endl); + << current->getServantName() << "]" << endl); auto sit = _servants.find(current->getServantName()); @@ -884,14 +903,14 @@ void ServantHandle::handleNoTarsProtocol(const TarsCurrentPtr ¤t) } catch(exception &ex) { - TLOGERROR("[TARS]ServantHandle::handleNoTarsProtocol " << ex.what() << endl); + TLOGERROR("[ServantHandle::handleNoTarsProtocol " << ex.what() << "]" << endl); } catch(...) { - TLOGERROR("[TARS]ServantHandle::handleNoTarsProtocol unknown error" << endl); + TLOGERROR("[ServantHandle::handleNoTarsProtocol unknown error]" << endl); } - if (current->isResponse()) + if (current->isResponse() && !buffer.empty()) { current->sendResponse((const char*)buffer.data(), buffer.size()); } diff --git a/servant/libservant/ServantProxy.cpp b/servant/libservant/ServantProxy.cpp index 2da75acb0180add8c60d28838a1f55160cf53af4..8b31cc1c0d4c248568244b9006daeb99ed086795 100644 --- a/servant/libservant/ServantProxy.cpp +++ b/servant/libservant/ServantProxy.cpp @@ -19,7 +19,7 @@ #include "servant/StatReport.h" #include "servant/Application.h" #include "servant/BaseF.h" -#include "servant/TarsLogger.h" +#include "servant/RemoteLogger.h" #include "servant/Message.h" #include "servant/EndpointManager.h" @@ -49,7 +49,7 @@ SeqManager::SeqManager(uint16_t iNum) for(uint16_t i=0;i<(uint16_t)iNum;i++) { _p[i].free = true; - _p[i].next = i+1; + _p[i].next = i + 1; } _p[iNum-1].next = MAX_UNSIGN_SHORT; _num = iNum; @@ -155,15 +155,23 @@ ServantProxyThreadData * ServantProxyThreadData::getData() return g_sp.get(); } -/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////// + ServantProxyCallback::ServantProxyCallback() : _bNetThreadProcess(false) { } +int ServantProxyCallback::dispatch(ReqMessagePtr msg) +{ + return onDispatch(msg); +} + +/////////////////////////////////////////////////////////////////////////////////////////// + int HttpServantProxyCallback::onDispatch(ReqMessagePtr msg) { - if (msg->response->iRet != tars::TARSSERVERSUCCESS) + if (msg->response->iRet != TARSSERVERSUCCESS) { return onDispatchException(msg->request, *msg->response); } @@ -178,12 +186,23 @@ HttpServantProxyCallback::HttpServantProxyCallback(const HttpCallbackPtr& cb) : int HttpServantProxyCallback::onDispatchException(const RequestPacket &request, const ResponsePacket &response) { - return _httpCb->onHttpResponseException(request.context, response.iRet); + if(_httpCb) + return _httpCb->onHttpResponseException(response.iRet); + + return 0; } int HttpServantProxyCallback::onDispatchResponse(const RequestPacket &request, const ResponsePacket &response) { - return _httpCb->onHttpResponse(request.context, response.status, response.sBuffer); + assert(response.sBuffer.size() == sizeof(shared_ptr)); + + shared_ptr rsp = *(shared_ptr*)(response.sBuffer.data()); + + + if(_httpCb) + return _httpCb->onHttpResponse(rsp); + + return 0; } /////////////////////////////////////////////////////////////// @@ -191,7 +210,7 @@ void coroWhenAll(const CoroParallelBasePtr &ptr) { if(!ptr->checkAllReqSend()) { - TLOGERROR("[TARS][coroWhenAll use coro invoke interface's num not equal ptr set value]"<_sched) { - TLOGERROR("[TARS][coroWhenAll no open coroutine mode]"<callback->onDispatch(msgPtr); + vMsg[i]->callback->dispatch(msgPtr); } } /////////////////////////////////////////////////////////////// string ServantProxy::STATUS_DYED_KEY = "STATUS_DYED_KEY"; -string ServantProxy::STATUS_GRID_KEY = "STATUS_GRID_KEY"; +//string ServantProxy::STATUS_GRID_KEY = "STATUS_GRID_KEY"; -string ServantProxy::STATUS_SAMPLE_KEY = "STATUS_SAMPLE_KEY"; +//string ServantProxy::STATUS_SAMPLE_KEY = "STATUS_SAMPLE_KEY"; string ServantProxy::STATUS_RESULT_CODE = "STATUS_RESULT_CODE"; @@ -229,10 +248,13 @@ string ServantProxy::STATUS_RESULT_DESC = "STATUS_RESULT_DESC"; string ServantProxy::STATUS_SETNAME_VALUE = "STATUS_SETNAME_VALUE"; -string ServantProxy::TARS_MASTER_KEY = "TARS_MASTER_KEY"; +//string ServantProxy::TARS_MASTER_KEY = "TARS_MASTER_KEY"; string ServantProxy::STATUS_TRACK_KEY = "STATUS_TRACK_KEY"; +// string ServantProxy::STATUS_COOKIE = "STATUS_COOKIE"; + + //////////////////////////////////// ServantProxy::ServantProxy(Communicator * pCommunicator, ObjectProxy ** ppObjectProxy, size_t iClientThreadNum) : _communicator(pCommunicator) @@ -288,6 +310,23 @@ string ServantProxy::tars_name() const return "NULL"; } +string ServantProxy::tars_full_name() const +{ + if (_objectProxyNum >= 1 && (*_objectProxy != NULL)) + { + return (*_objectProxy)->name() +"#" + (*_objectProxy)->hash() + "@" + (*_objectProxy)->address(); + } + return "NULL"; +} + + +void ServantProxy::tars_reconnect(int second) +{ + if (_objectProxyNum >= 1 && (*_objectProxy != NULL)) + { + (*_objectProxy)->reconnect(second); + } +} TC_Endpoint ServantProxy::tars_invoke_endpoint() { @@ -346,17 +385,68 @@ int ServantProxy::tars_async_timeout() const return _asyncTimeout; } +void ServantProxy::tars_connection_serial(int connectionSerial) +{ + assert(!_rootPrx); + _connectionSerial = connectionSerial; +} + +int ServantProxy::tars_connection_serial() const +{ + if(_rootPrx) { + return _rootPrx->tars_connection_serial(); + } + + return _connectionSerial; +} + +void ServantProxy::tars_set_protocol(SERVANT_PROTOCOL protocol, int connectionSerial) +{ + ProxyProtocol proto; + + switch(protocol) + { + case PROTOCOL_HTTP1: + proto.requestFunc = ProxyProtocol::http1Request; + proto.responseFunc = ProxyProtocol::http1Response; + + if(connectionSerial <= 0) + connectionSerial = DEFAULT_CONNECTION_SERIAL; + break; +#if TARS_HTTP2 + case PROTOCOL_HTTP2: + proto.requestFunc = ProxyProtocol::http2Request; + proto.responseFunc = ProxyProtocol::http2Response; + connectionSerial = 0; + break; +#endif + case PROTOCOL_TARS: + default: + proto.requestFunc = ProxyProtocol::tarsRequest; + proto.responseFunc = ProxyProtocol::tarsResponse; + break; + } + tars_set_protocol(proto, connectionSerial); +} -void ServantProxy::tars_set_protocol(const ProxyProtocol& protocol) +void ServantProxy::tars_set_protocol(const ProxyProtocol& protocol, int connectionSerial) { TC_LockT lock(*this); - for(size_t i = 0;i < _objectProxyNum; ++i) + for (size_t i = 0; i < _objectProxyNum; ++i) { (*(_objectProxy + i))->setProxyProtocol(protocol); } + + _connectionSerial = connectionSerial; } +ProxyProtocol ServantProxy::tars_get_protocol() +{ + TC_LockT lock(*this); + + return (*(_objectProxy + 0))->getProxyProtocol(); +} void ServantProxy::tars_set_sockopt(int level, int optname, const void * optval, SOCKET_LEN_TYPE optlen) { @@ -406,9 +496,9 @@ void ServantProxy::tars_ping() map s; - tars::TarsOutputStream os; + TarsOutputStream os; - tars_invoke(tars::TARSNORMAL, "tars_ping", os, m, s); + tars_invoke(TARSNORMAL, "tars_ping", os, m, s); } @@ -417,9 +507,9 @@ void ServantProxy::tars_async_ping() map m; map s; - tars::TarsOutputStream os; + TarsOutputStream os; - tars_invoke_async(tars::TARSONEWAY, "tars_ping", os, m, s, NULL); + tars_invoke_async(TARSONEWAY, "tars_ping", os, m, s, NULL); } ServantProxy* ServantProxy::tars_hash(int64_t key) @@ -508,7 +598,7 @@ void ServantProxy::tars_set_push_callback(const ServantProxyCallbackPtr & cb) // } // else // { -// TLOGERROR("[TAF][ServantProxy::invoke_async use coroutine's callback not set CoroParallelBasePtr]" << endl); +// TLOGERROR("[ServantProxy::invoke_async use coroutine's callback not set CoroParallelBasePtr]" << endl); // delete msg; // msg = NULL; // throw TarsUseCoroException("ServantProxy::invoke_async use coroutine's callback not set CoroParallelBasePtr"); @@ -516,7 +606,7 @@ void ServantProxy::tars_set_push_callback(const ServantProxyCallbackPtr & cb) // } // else // { -// TLOGERROR("[TAF][ServantProxy::invoke coroutine mode invoke not open]" << endl); +// TLOGERROR("[ServantProxy::invoke coroutine mode invoke not open]" << endl); // delete msg; // msg = NULL; // throw TarsUseCoroException("coroutine mode invoke not open"); @@ -527,7 +617,7 @@ void ServantProxy::tars_set_push_callback(const ServantProxyCallbackPtr & cb) // bool bEmpty; // if (!pReqQ->push_back(msg, bEmpty)) // { -// TLOGERROR("[TAF][ServantProxy::invoke_async msgQueue push_back error num:" << pSptd->_netSeq << "]" << endl); +// TLOGERROR("[ServantProxy::invoke_async msgQueue push_back error num:" << pSptd->_netSeq << "]" << endl); // msg->pObjectProxy->getCommunicatorEpoll()->notify(pSptd->_reqQNo, pReqQ); // delete msg; // throw TarsClientQueueException("client queue full"); @@ -560,11 +650,12 @@ void ServantProxy::invoke(ReqMessage * msg, bool bCoroAsync) if(msg->bDyeing) { - TLOGTARS("[TARS][ServantProxy::invoke, set dyeing, key=" << pSptd->_dyeingKey << endl); + TLOGTARS("[ServantProxy::invoke, set dyeing, key=" << pSptd->_dyeingKey << endl); } + msg->cookie = pSptd->_cookie; -#ifdef _USE_OPENTRACKING +#ifdef TARS_OPENTRACKING msg->trackInfoMap = pSptd->_trackInfoMap; #endif @@ -591,10 +682,10 @@ void ServantProxy::invoke(ReqMessage * msg, bool bCoroAsync) //如果是按set规则调用 if (pObjProxy && pObjProxy->isInvokeBySet()) { - SET_MSG_TYPE(msg->request.iMessageType, tars::TARSMESSAGETYPESETNAME); + SET_MSG_TYPE(msg->request.iMessageType, TARSMESSAGETYPESETNAME); msg->request.status[ServantProxy::STATUS_SETNAME_VALUE] = pObjProxy->getInvokeSetName(); - TLOGTARS("[TARS][ServantProxy::invoke, " << msg->request.sServantName << ", invoke with set,"<getInvokeSetName()<<"]" << endl); + TLOGTARS("[ServantProxy::invoke, " << msg->request.sServantName << ", invoke with set,"<getInvokeSetName()<<"]" << endl); } //同步调用 new 一个ReqMonitor @@ -633,7 +724,7 @@ void ServantProxy::invoke(ReqMessage * msg, bool bCoroAsync) } else { - TLOGERROR("[TARS][ServantProxy::invoke use coroutine's callback not set CoroParallelBasePtr]"<push_back(msg,bEmpty)) { - TLOGERROR("[TARS][ServantProxy::invoke msgQueue push_back error num:" << pSptd->_netSeq << "]" << endl); + TLOGERROR("[ServantProxy::invoke msgQueue push_back error num:" << pSptd->_netSeq << "]" << endl); delete msg; msg = NULL; @@ -692,7 +783,7 @@ void ServantProxy::invoke(ReqMessage * msg, bool bCoroAsync) //判断eStatus来判断状态 assert(msg->eStatus != ReqMessage::REQ_REQ); - TLOGTARS("[TARS]ServantProxy::invoke line: " << __LINE__ << " status: " << msg->eStatus << ", ret: " <response->iRet << endl); +// TLOGTARS("[ServantProxy::invoke line: " << __LINE__ << " status: " << msg->eStatus << ", ret: " <response->iRet << endl); if(msg->eStatus == ReqMessage::REQ_RSP && msg->response->iRet == TARSSERVERSUCCESS) { @@ -742,7 +833,7 @@ void ServantProxy::invoke(ReqMessage * msg, bool bCoroAsync) ////////////////////////////////////////////////////////////////// void ServantProxy::tars_invoke_async(char cPacketType, const string &sFuncName, - tars::TarsOutputStream &buf, + TarsOutputStream &buf, const map& context, const map& status, const ServantProxyCallbackPtr& callback, @@ -764,20 +855,57 @@ void ServantProxy::tars_invoke_async(char cPacketType, msg->request.status = status; msg->request.iTimeout = _asyncTimeout; - // 在RequestPacket中的context设置主调信息 - if(_masterFlag) - { - msg->request.context.insert(std::make_pair(TARS_MASTER_KEY,ClientConfig::ModuleName)); //TARS_MASTER_KEY clientConfig.ModuleName - } +// // 在RequestPacket中的context设置主调信息 +// if(_masterFlag) +// { +// msg->request.context.insert(std::make_pair(TARS_MASTER_KEY,ClientConfig::ModuleName)); //TARS_MASTER_KEY clientConfig.ModuleName +// } checkDye(msg->request); - invoke(msg, bCoro); + checkCookie(msg->request); + servant_invoke(msg, bCoro); +} + + +////////////////////////////////////////////////////////////////// +void ServantProxy::tars_invoke_async(char cPacketType, + const string &sFuncName, + const vector &buf, + const map& context, + const map& status, + const ServantProxyCallbackPtr& callback, + bool bCoro) +{ + ReqMessage * msg = new ReqMessage(); + + msg->init(callback?ReqMessage::ASYNC_CALL:ReqMessage::ONE_WAY); + msg->callback = callback; + + msg->request.iVersion = TARSVERSION; + msg->request.cPacketType = (callback ? cPacketType : TARSONEWAY); + msg->request.sFuncName = sFuncName; + msg->request.sServantName = (*_objectProxy)->name(); + msg->request.sBuffer = buf; + msg->request.context = context; + msg->request.status = status; + msg->request.iTimeout = _asyncTimeout; + +// // 在RequestPacket中的context设置主调信息 +// if(_masterFlag) +// { +// msg->request.context.insert(std::make_pair(TARS_MASTER_KEY,ClientConfig::ModuleName)); //TARS_MASTER_KEY clientConfig.ModuleName +// } + + checkDye(msg->request); + + checkCookie(msg->request); + servant_invoke(msg, bCoro); } shared_ptr ServantProxy::tars_invoke(char cPacketType, const string& sFuncName, - tars::TarsOutputStream& buf, + const vector& buf, const map& context, const map& status) // ResponsePacket& rsp) @@ -791,20 +919,65 @@ shared_ptr ServantProxy::tars_invoke(char cPacketType, msg->request.sFuncName = sFuncName; msg->request.sServantName = (*_objectProxy)->name(); - buf.swap(msg->request.sBuffer); + msg->request.sBuffer = buf; msg->request.context = context; msg->request.status = status; msg->request.iTimeout = _syncTimeout; - // 在RequestPacket中的context设置主调信息 - if(_masterFlag) - { - msg->request.context.insert(std::make_pair(TARS_MASTER_KEY,ClientConfig::ModuleName)); - } +// // 在RequestPacket中的context设置主调信息 +// if(_masterFlag) +// { +// msg->request.context.insert(std::make_pair(TARS_MASTER_KEY,ClientConfig::ModuleName)); +// } + + checkDye(msg->request); + + checkCookie(msg->request); + + invoke(msg); + + shared_ptr rsp = msg->response; + // rsp = msg->response; + + delete msg; + msg = NULL; + + return rsp; + +} + + +shared_ptr ServantProxy::tars_invoke(char cPacketType, + const string& sFuncName, + TarsOutputStream& buf, + const map& context, + const map& status) + // ResponsePacket& rsp) +{ + ReqMessage * msg = new ReqMessage(); + + msg->init(ReqMessage::SYNC_CALL); + msg->request.iVersion = TARSVERSION; + msg->request.cPacketType = cPacketType; + msg->request.sFuncName = sFuncName; + msg->request.sServantName = (*_objectProxy)->name(); + + buf.swap(msg->request.sBuffer); + msg->request.context = context; + msg->request.status = status; + msg->request.iTimeout = _syncTimeout; + +// // 在RequestPacket中的context设置主调信息 +// if(_masterFlag) +// { +// msg->request.context.insert(std::make_pair(TARS_MASTER_KEY,ClientConfig::ModuleName)); +// } checkDye(msg->request); + checkCookie(msg->request); + invoke(msg); shared_ptr rsp = msg->response; @@ -828,13 +1001,13 @@ void ServantProxy::rpc_call(uint32_t iRequestId, msg->init(ReqMessage::SYNC_CALL); msg->bFromRpc = true; - msg->request.sFuncName = sFuncName; - + msg->request.sServantName = (*_objectProxy)->name(); + msg->request.sFuncName = sFuncName; msg->request.iRequestId = iRequestId; msg->request.sBuffer.assign(buff, buff + len); - invoke(msg); + servant_invoke(msg, false); rsp = *msg->response.get(); @@ -852,66 +1025,180 @@ void ServantProxy::rpc_call_async(uint32_t iRequestId, ReqMessage * msg = new ReqMessage(); msg->init(callback?ReqMessage::ASYNC_CALL:ReqMessage::ONE_WAY); - msg->request.sFuncName = sFuncName; + msg->bFromRpc = true; msg->callback = callback; + msg->request.sServantName = (*_objectProxy)->name(); + msg->request.sFuncName = sFuncName; msg->request.iRequestId = iRequestId; msg->request.sBuffer.assign(buff, buff + len); - invoke(msg, bCoro); + servant_invoke(msg, bCoro); } -void ServantProxy::http_call(const std::string& method, - const std::string& uri, - const std::map& headers, - const std::string& body, - std::map& rheaders, - std::string& rbody) +ServantPrx ServantProxy::getServantPrx(ReqMessage *msg) { - ReqMessage* msg = new ReqMessage(); + if(_servantId == 0) + { + std::lock_guard m(_servantMutex); - msg->init(ReqMessage::SYNC_CALL); + if(_servantId == 0 && _servantList.empty()) + { + for(int i = 0; i < _connectionSerial; ++i) + { + string obj = tars_name() + "#" + TC_Common::tostr(i); + if (!(*_objectProxy)->address().empty()) + { + obj += "@" + (*_objectProxy)->address(); + } - msg->bFromRpc = true; - msg->request.sServantName = uri; - msg->request.sFuncName = method; - // 使用下面两个字段保存头部和包体 - msg->request.context = headers; + ServantPrx prx = _communicator->stringToProxy(obj); + prx->tars_set_protocol(tars_get_protocol()); + prx->_rootPrx = this; - msg->request.sBuffer.assign(body.begin(), body.end()); + _servantList.push_back(prx); + } + } + } - invoke(msg); +// assert((int)_servantList.size() == _connectionSerial); - rheaders.swap(msg->response->status); - rbody.assign(msg->response->sBuffer.begin(), msg->response->sBuffer.end()); + int id = _servantId % (_servantList.size() + 1); - delete msg; - msg = NULL; + ++_servantId; + + if(id == 0) + { + return this; + } + + return _servantList[(id-1)]; +// return _servantList[(_servantId++) % _servantList.size()]; } -void ServantProxy::http_call_async(const std::string& method, - const std::string& uri, - const std::map& headers, - const std::string& body, - const HttpCallbackPtr &cb) +void ServantProxy::onNotifyEndpoints(size_t netThreadSeq, const set & active,const set & inactive) { - ReqMessage * msg = new ReqMessage(); + for (size_t i = 0; i < _servantList.size(); i++) + { + _servantList[i]->_objectProxy[netThreadSeq]->getEndpointManager()->updateEndpoints(active, inactive); + } - msg->init(ReqMessage::ASYNC_CALL); +// _objectProxy[netThreadSeq]->getEndpointManager()->updateEndpoints(active, inactive); +} - msg->bFromRpc = true; - msg->request.sServantName = uri; - msg->request.sFuncName = method; - // 使用下面两个字段保存头部和包体 - msg->request.context = headers; - msg->request.sBuffer.assign(body.begin(), body.end()); +void ServantProxy::onSetInactive(const EndpointInfo& ep) +{ + if(!_rootPrx) + return; + + for (size_t i = 0; i < _rootPrx->_servantList.size(); i++) + { + ServantPrx &prx = _rootPrx->_servantList[i]; + + for (size_t i = 0; i < prx->_objectProxyNum; ++i) + { + prx->_objectProxy[i]->onSetInactive(ep); + } + } +} - ServantProxyCallbackPtr callback = new HttpServantProxyCallback(cb); - msg->callback = callback; +int ServantProxy::servant_invoke(ReqMessage *msg, bool bCoroAsync) +{ + ServantPrx prx = getServantPrx(msg); - invoke(msg); + if(msg->callback) + { + msg->callback->setServantPrx(prx); + } + + prx->invoke(msg, bCoroAsync); + + return 0; +} + +void ServantProxy::http_call(const string &funcName, shared_ptr &request, shared_ptr &response) +{ + // if(_connectionSerial <= 0) { + // _connectionSerial = DEFAULT_CONNECTION_SERIAL; + // } + + ReqMessage* msg = new ReqMessage(); + + msg->init(ReqMessage::SYNC_CALL); + + msg->bFromRpc = true; + + msg->request.sServantName = (*_objectProxy)->name(); + msg->request.sFuncName = funcName; + + msg->request.sBuffer.resize(sizeof(shared_ptr)); + + msg->deconstructor = [msg] { + shared_ptr & data = *(shared_ptr *) (msg->request.sBuffer.data()); + data.reset(); + + if(!msg->response->sBuffer.empty()) + { + shared_ptr & rsp = *(shared_ptr *) (msg->response->sBuffer.data()); + //主动reset一次 + rsp.reset(); + + msg->response->sBuffer.clear(); + } + }; + + shared_ptr & data = *(shared_ptr *) (msg->request.sBuffer.data()); + + data = request; + + servant_invoke(msg, false); + + response = *(shared_ptr*)(msg->response->sBuffer.data()); + + delete msg; + msg = NULL; +} + +void ServantProxy::http_call_async(const string &funcName, shared_ptr &request, const HttpCallbackPtr &cb, bool bCoro) +{ + // if(_connectionSerial <= 0) { + // _connectionSerial = DEFAULT_CONNECTION_SERIAL; + // } + + ReqMessage* msg = new ReqMessage(); + + msg->init(ReqMessage::ASYNC_CALL); + + msg->bFromRpc = true; + + msg->request.sServantName = (*_objectProxy)->name(); + msg->request.sFuncName = funcName; + + msg->request.sBuffer.resize(sizeof(shared_ptr)); + + msg->deconstructor = [msg] { + shared_ptr & data = *(shared_ptr *) (msg->request.sBuffer.data()); + data.reset(); + + if(!msg->response->sBuffer.empty()) + { + shared_ptr & rsp = *(shared_ptr *) (msg->response->sBuffer.data()); + //主动reset一次 + rsp.reset(); + + msg->response->sBuffer.clear(); + } + }; + + *(shared_ptr*)(msg->request.sBuffer.data()) = request; + + ServantProxyCallbackPtr callback = new HttpServantProxyCallback(cb); + + msg->callback = callback; + + servant_invoke(msg, bCoro); } //选取一个网络线程对应的信息 @@ -964,12 +1251,23 @@ void ServantProxy::checkDye(RequestPacket& req) assert(pSptd != NULL); if(pSptd && pSptd->_dyeing) { - SET_MSG_TYPE(req.iMessageType, tars::TARSMESSAGETYPEDYED); + SET_MSG_TYPE(req.iMessageType, TARSMESSAGETYPEDYED); req.status[ServantProxy::STATUS_DYED_KEY] = pSptd->_dyeingKey; } } +void ServantProxy::checkCookie(RequestPacket& req) +{ + //线程私有数据 + ServantProxyThreadData * pSptd = ServantProxyThreadData::getData(); + assert(pSptd != NULL); + + std::for_each(pSptd->_cookie.begin(), pSptd->_cookie.end(),[&](map::value_type& p){ + req.status.insert(make_pair(p.first, p.second)); + }); +} + void ServantProxy::tars_endpoints(vector &activeEndPoint, vector &inactiveEndPoint) { diff --git a/servant/libservant/ServantProxyFactory.cpp b/servant/libservant/ServantProxyFactory.cpp index 4d588f80f4aab61f7c8ffae43d9943ebd27d3f01..bd8893948042694d3992ed9200babe995544b3ef 100644 --- a/servant/libservant/ServantProxyFactory.cpp +++ b/servant/libservant/ServantProxyFactory.cpp @@ -15,7 +15,7 @@ */ #include "servant/ServantProxyFactory.h" -#include "servant/TarsLogger.h" +#include "servant/RemoteLogger.h" namespace tars { diff --git a/servant/libservant/StatReport.cpp b/servant/libservant/StatReport.cpp index e67ff40f4b1237deb64d642b4d4c622847abe737..e5018ac7a9a9425343fdfe846a31739217721833 100755 --- a/servant/libservant/StatReport.cpp +++ b/servant/libservant/StatReport.cpp @@ -17,8 +17,9 @@ #include "servant/StatReport.h" #include "util/tc_common.h" #include "util/tc_timeprovider.h" -#include "servant/TarsLogger.h" +#include "servant/RemoteLogger.h" #include "servant/Communicator.h" +#include "servant/Application.h" #include namespace tars @@ -36,7 +37,7 @@ StatReport::StatReport(size_t iEpollNum) , _epollNum(iEpollNum) , _retValueNumLimit(10) { - srand(time(NULL)); + srand(time(NULL)); for(size_t i = 0 ; i < _epollNum; i++) { @@ -81,7 +82,7 @@ void StatReport::report(size_t iSeq,MapStatMicMsg * pmStatMicMsg) delete pmStatMicMsg; pmStatMicMsg = NULL; - TLOGERROR("[TARS][StatReport::report] queue full." << endl); + TLOGERROR("[StatReport::report] queue full]" << endl); } } @@ -318,17 +319,19 @@ void StatReport::report(const string& strModuleName, } head.interfaceName = trimAndLimitStr(strInterfaceName, MAX_MASTER_NAME_LEN); + head.slavePort = iPort; + head.returnValue = iReturnValue; - + //包体信息. - if(eResult == STAT_SUCC) + if (eResult == STAT_SUCC) { body.count = 1; body.totalRspTime = body.minRspTime = body.maxRspTime = iSptime; } - else if(eResult == STAT_TIMEOUT) + else if (eResult == STAT_TIMEOUT) { body.timeoutCount = 1; } @@ -381,23 +384,24 @@ void StatReport::report(const string& strMasterName, submit(head, body, true); } - -string StatReport::sampleUnid() -{ - static atomic g_id(rand()); - - char s[14] = {0}; - time_t t = TNOW; - int ip = inet_addr(_ip.c_str()); - int thread = ++g_id; - static unsigned short n = 0; - ++n; - memcpy( s, &ip, 4 ); - memcpy( s + 4, &t, 4); - memcpy( s + 8, &thread, 4); - memcpy( s + 12, &n, 2 ); - return TC_Common::bin2str(string(s,14)); -} +// +//string StatReport::sampleUnid() +//{ +// +// static atomic g_id(rand()); +// +// char s[14] = { 0 }; +// time_t t = TNOW; +// int ip = inet_addr(_ip.c_str()); +// int thread = ++g_id; +// static unsigned short n = 0; +// ++n; +// memcpy(s, &ip, 4); +// memcpy(s + 4, &t, 4); +// memcpy(s + 8, &thread, 4); +// memcpy(s + 12, &n, 2); +// return TC_Common::bin2str(string(s, 14)); +//} void StatReport::submit( StatMicMsgHead& head, StatMicMsgBody& body,bool bFromClient ) { @@ -430,13 +434,23 @@ void StatReport::submit( StatMicMsgHead& head, StatMicMsgBody& body,bool bFromCl } } -void StatReport::doSample(const string& strSlaveName, - const string& strInterfaceName, - const string& strSlaveIp, - map &status) +size_t StatReport::getQueueSize(size_t epollIndex) { + if(epollIndex >= _statMsg.size()) + { + return 0; + } + + return _statMsg[epollIndex]->size(); } +//void StatReport::doSample(const string& strSlaveName, +// const string& strInterfaceName, +// const string& strSlaveIp, +// map& status) +//{ +//} + int StatReport::reportMicMsg(MapStatMicMsg& msg,bool bFromClient) { if (msg.empty()) return 0; @@ -452,7 +466,7 @@ int StatReport::reportMicMsg(MapStatMicMsg& msg,bool bFromClient) msg.swap(mStatMsg); } - TLOGTARS("[TARS][StatReport::reportMicMsg get size:" << mStatMsg.size()<<"]"<< endl); + TLOGTARS("[StatReport::reportMicMsg get size:" << mStatMsg.size()<<"]"<< endl); for(MapStatMicMsg::iterator it = mStatMsg.begin(); it != mStatMsg.end(); it++) { const StatMicMsgHead &head = it->first; @@ -463,30 +477,30 @@ int StatReport::reportMicMsg(MapStatMicMsg& msg,bool bFromClient) { if(_statPrx) { - TLOGTARS("[TARS][StatReport::reportMicMsg send size:" << mTemp.size()<<"]"<< endl); - _statPrx->tars_set_timeout(_reportTimeout)->async_reportMicMsg(NULL,mTemp,bFromClient); + TLOGTARS("[StatReport::reportMicMsg send size:" << mTemp.size()<<"]"<< endl); + _statPrx->tars_set_timeout(_reportTimeout)->async_reportMicMsg(NULL,mTemp,bFromClient, ServerConfig::Context); } iLen = iTemLen; mTemp.clear(); } mTemp[head] = it->second; - if(LOG->isNeedLog(TarsRollLogger::INFO_LOG)) + if(LOG->isNeedLog(LocalRollLogger::INFO_LOG)) { ostringstream os; os.str(""); head.displaySimple(os); os << " "; mTemp[head].displaySimple(os); - TLOGTARS("[TARS][StatReport::reportMicMsg display:" << os.str() << endl); + TLOGTARS("[StatReport::reportMicMsg display:" << os.str() << "]" << endl); } } if(0 != (int)mTemp.size()) { if(_statPrx) { - TLOGTARS("[TARS][StatReport::reportMicMsg send size:" << mTemp.size()<<"]"<< endl); - _statPrx->tars_set_timeout(_reportTimeout)->async_reportMicMsg(NULL,mTemp,bFromClient); + TLOGTARS("[StatReport::reportMicMsg send size:" << mTemp.size()<<"]"<< endl); + _statPrx->tars_set_timeout(_reportTimeout)->async_reportMicMsg(NULL,mTemp,bFromClient, ServerConfig::Context); } } return 0; @@ -593,19 +607,19 @@ int StatReport::reportPropMsg() } } mStatMsg[head] = body; - if(LOG->isNeedLog(TarsRollLogger::INFO_LOG)) + if(LOG->isNeedLog(LocalRollLogger::INFO_LOG)) { ostringstream os; os.str(""); head.displaySimple(os); os << " "; mStatMsg[head].displaySimple(os); - TLOGTARS("[TARS][StatReport::reportPropMsg display:" << os.str() << endl); + TLOGTARS("[StatReport::reportPropMsg display:" << os.str() << "]" << endl); } } } - TLOGTARS("[TARS][StatReport::reportPropMsg get size:" << mStatMsg.size()<<"]"<< endl); + TLOGTARS("[StatReport::reportPropMsg get size:" << mStatMsg.size()<<"]"<< endl); int iLen = 0; MapStatPropMsg mTemp; for(MapStatPropMsg::iterator it = mStatMsg.begin(); it != mStatMsg.end(); it++) @@ -624,7 +638,7 @@ int StatReport::reportPropMsg() { if(_propertyPrx) { - TLOGTARS("[TARS][StatReport::reportPropMsg send size:" << mTemp.size()<<"]"<< endl); + TLOGTARS("[StatReport::reportPropMsg send size:" << mTemp.size()<<"]"<< endl); _propertyPrx->tars_set_timeout(_reportTimeout)->async_reportPropMsg(NULL,mTemp); } iLen = iTemLen; @@ -636,7 +650,7 @@ int StatReport::reportPropMsg() { if(_propertyPrx) { - TLOGTARS("[TARS][StatReport::reportPropMsg send size:" << mTemp.size()<< "]"<< endl); + TLOGTARS("[StatReport::reportPropMsg send size:" << mTemp.size()<< "]"<< endl); _propertyPrx->tars_set_timeout(_reportTimeout)->async_reportPropMsg(NULL,mTemp); } } @@ -663,7 +677,7 @@ int StatReport::reportSampleMsg() _statSampleMsg.swap(mmStatSampleMsg); } - TLOGTARS("[TARS][StatReport::reportSampleMsg get size:" << mmStatSampleMsg.size()<<"]"<< endl); + TLOGTARS("[StatReport::reportSampleMsg get size:" << mmStatSampleMsg.size()<<"]"<< endl); int iLen = 0; vector vTemp; @@ -676,8 +690,8 @@ int StatReport::reportSampleMsg() { if(_statPrx) { - TLOGTARS("[TARS][StatReport::reportSampleMsg send size:" << vTemp.size()<< "]"<< endl); - _statPrx->tars_set_timeout(_reportTimeout)->async_reportSampleMsg(NULL,vTemp); + TLOGTARS("[StatReport::reportSampleMsg send size:" << vTemp.size()<< "]"<< endl); + _statPrx->tars_set_timeout(_reportTimeout)->async_reportSampleMsg(NULL,vTemp, ServerConfig::Context); } iLen = iTemLen; vTemp.clear(); @@ -688,8 +702,8 @@ int StatReport::reportSampleMsg() { if(_statPrx) { - TLOGTARS("[TARS][StatReport::reportSampleMsg send size:" << vTemp.size()<< "]"<< endl); - _statPrx->tars_set_timeout(_reportTimeout)->async_reportSampleMsg(NULL,vTemp); + TLOGTARS("[StatReport::reportSampleMsg send size:" << vTemp.size()<< "]"<< endl); + _statPrx->tars_set_timeout(_reportTimeout)->async_reportSampleMsg(NULL,vTemp, ServerConfig::Context); } } @@ -697,11 +711,11 @@ int StatReport::reportSampleMsg() } catch ( exception& e ) { - TLOGERROR("StatReport::reportSampleMsg catch exception:" << e.what() << endl); + TLOGERROR("[StatReport::reportSampleMsg catch exception:" << e.what() << "]" << endl); } catch ( ... ) { - TLOGERROR("StatReport::reportSampleMsg catch unkown exception" << endl); + TLOGERROR("[StatReport::reportSampleMsg catch unkown exception]" << endl); } return -1; } diff --git a/servant/libservant/Transceiver.cpp b/servant/libservant/Transceiver.cpp index 9ce715af00f773e760999b34a0dd330e9807352a..56f6b9228b22e39edfb8f4849aa0d729ab566212 100755 --- a/servant/libservant/Transceiver.cpp +++ b/servant/libservant/Transceiver.cpp @@ -17,7 +17,7 @@ #include "servant/Transceiver.h" #include "servant/AdapterProxy.h" #include "servant/Application.h" -#include "servant/TarsLogger.h" +#include "servant/RemoteLogger.h" #include "servant/AuthLogic.h" #if TARS_SSL @@ -57,7 +57,7 @@ void Transceiver::checkTimeout() if(eConnecting == _connStatus && TNOWMS > _conTimeoutTime) { //链接超时 - TLOGERROR("[TARS][Transceiver::checkTimeout ep:"<<_adapterProxy->endpoint().desc()<<" , connect timeout]"<endpoint().desc()<<" , connect timeout]"<setConTimeout(true); close(); } @@ -70,8 +70,6 @@ bool Transceiver::isSSL() const void Transceiver::reconnect() { - close(); - connect(); } @@ -120,7 +118,7 @@ void Transceiver::connect() _fd = fd; - TLOGTARS("[TARS][Transceiver::connect obj:" << _adapterProxy->getObjProxy()->name() + TLOGTARS("[Transceiver::connect obj:" << _adapterProxy->getObjProxy()->name() << ",connect:" << _ep.desc() << ",fd:" << _fd << "]" << endl); // //设置网络qos的dscp标志 @@ -136,7 +134,7 @@ void Transceiver::connect() { if(setsockopt(_fd,socketOpts[i].level,socketOpts[i].optname, (const char*)socketOpts[i].optval,socketOpts[i].optlen) == -1) { - TLOGERROR("[TARS][setsockopt error:" << NetworkUtil::errorToString(errno) + TLOGERROR("[setsockopt error:" << NetworkUtil::errorToString(errno) << ",objname:" << _adapterProxy->getObjProxy()->name() << ",desc:" << _ep.desc() << ",fd:" << _fd @@ -154,9 +152,15 @@ void Transceiver::setConnected() _adapterProxy->setConTimeout(false); _adapterProxy->addConnExc(false); - TLOGTARS("[TARS][tcp setConnected, " << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "]" << endl); + TLOGTARS("[tcp setConnected, " << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "]" << endl); onConnect(); + + if(_adapterProxy->getObjProxy()->getPushCallback()) + { + _adapterProxy->getObjProxy()->getPushCallback()->onConnect(_ep.getEndpoint()); + } + _adapterProxy->onConnect(); } void Transceiver::onConnect() @@ -168,7 +172,7 @@ void Transceiver::onConnect() if (!_openssl) { ObjectProxy* obj = _adapterProxy->getObjProxy(); - TLOGERROR("[TARS][onConnect:" << obj->name() << " can't find client SSL_CTX " << endl); + TLOGERROR("[onConnect:" << obj->name() << " can't find client SSL_CTX " << endl); this->close(); return; } @@ -178,10 +182,11 @@ void Transceiver::onConnect() _openssl->setReadBufferSize(1024 * 8); _openssl->setWriteBufferSize(1024 * 8); + _openssl->recvBuffer()->setConnection(this); int ret = _openssl->doHandshake(_sendBuffer); if (ret != 0) { - TLOGERROR("[TARS] SSL_connect failed " << endl); + TLOGERROR(" SSL_connect failed " << endl); this->close(); return; } @@ -189,7 +194,7 @@ void Transceiver::onConnect() // send the encrypt data from write buffer if (!_sendBuffer.empty()) { - TLOGTARS("[TARS][Transceiver::onConnect handshake:" << _openssl->isHandshaked() << ", send handshake len:" << _sendBuffer.getBufferLength() << endl); + TLOGTARS("[Transceiver::onConnect handshake:" << _openssl->isHandshaked() << ", send handshake len:" << _sendBuffer.getBufferLength() << endl); doRequest(); } @@ -204,12 +209,12 @@ void Transceiver::doAuthReq() { ObjectProxy* obj = _adapterProxy->getObjProxy(); - TLOGTARS("[TARS][Transceiver::doAuthReq obj:" << obj->name() << ", auth type:" << etos((AUTH_TYPE)_adapterProxy->endpoint().authType()) << endl); + TLOGTARS("[Transceiver::doAuthReq obj:" << obj->name() << ", auth type:" << etos((AUTH_TYPE)_adapterProxy->endpoint().authType()) << endl); if (_adapterProxy->endpoint().authType() == AUTH_TYPENONE) { _authState = AUTH_SUCC; - _adapterProxy->doInvoke(); + _adapterProxy->doInvoke(true); } else { @@ -281,7 +286,7 @@ void Transceiver::doAuthReq() // // if (ret == TC_NetWorkBuffer::PACKET_ERR) // { -// TLOGERROR("[TAF][tcp doResponse," << _pAdapterProxy->getObjProxy()->name() << ",fd:" << _iFd << "," << _ep.desc() << ",tcp recv decode error" << endl); +// TLOGERROR("[tcp doResponse," << _pAdapterProxy->getObjProxy()->name() << ",fd:" << _iFd << "," << _ep.desc() << ",tcp recv decode error" << endl); // msg->eStatus = ReqMessage::REQ_NET; // msg->response->sResultDesc = "recv packet decode failed"; // @@ -295,7 +300,7 @@ void Transceiver::doAuthReq() // } // catch (exception & ex) { // TLOGERROR( -// "[TAF][tcp doResponse," << _pAdapterProxy->getObjProxy()->name() << ",fd:" << _iFd << "," << _ep.desc() << ",tcp recv decode error:" << ex.what() << endl); +// "[tcp doResponse," << _pAdapterProxy->getObjProxy()->name() << ",fd:" << _iFd << "," << _ep.desc() << ",tcp recv decode error:" << ex.what() << endl); // msg->eStatus = ReqMessage::REQ_NET; // msg->response->sResultDesc = "recv packet decode failed"; // @@ -303,7 +308,7 @@ void Transceiver::doAuthReq() // } // catch (...) { // TLOGERROR( -// "[TAF][tcp doResponse," << _pAdapterProxy->getObjProxy()->name() << ",fd:" << _iFd << "," << _ep.desc() << ",tcp recv decode error." << endl); +// "[tcp doResponse," << _pAdapterProxy->getObjProxy()->name() << ",fd:" << _iFd << "," << _ep.desc() << ",tcp recv decode error." << endl); // msg->eStatus = ReqMessage::REQ_NET; // msg->response->sResultDesc = "recv packet decode failed"; // } @@ -320,24 +325,24 @@ void Transceiver::doAuthReq() void Transceiver::finishInvoke(shared_ptr &rsp) { - if (_authState != AUTH_SUCC) + if (_adapterProxy->endpoint().authType() == AUTH_TYPELOCAL && _authState != AUTH_SUCC) { std::string ret(rsp->sBuffer.begin(), rsp->sBuffer.end()); tars::AUTH_STATE tmp = AUTH_SUCC; tars::stoe(ret, tmp); tars::AUTH_STATE newstate = tmp; - TLOGTARS("[TARS]Transceiver::finishInvoke state: " << etos(_authState) << " -> " << etos(newstate) << endl); + TLOGTARS("Transceiver::finishInvoke state: " << etos(_authState) << " -> " << etos(newstate) << endl); setAuthState(newstate); if (newstate == AUTH_SUCC) { // flush old buffered msg when auth is not complete - _adapterProxy->doInvoke(); + _adapterProxy->doInvoke(true); } else { - TLOGERROR("[TARS]Transceiver::finishInvoke newstate: " << etos(newstate) << ", error close!\n"); + TLOGERROR("Transceiver::finishInvoke newstate: " << etos(newstate) << ", error close!\n"); close(); } @@ -372,7 +377,7 @@ bool Transceiver::sendAuthData(const BasicAuthInfo& info) int ret = _openssl->write(buff.data(), (uint32_t) buff.size(), _sendBuffer); if(ret != 0) { - TLOGERROR("[TARS][Transceiver::sendAuthData ssl write failed, obj:" << _adapterProxy->getObjProxy()->name() << ", error:" << _openssl->getErrMsg() << endl); + TLOGERROR("[Transceiver::sendAuthData ssl write failed, obj:" << _adapterProxy->getObjProxy()->name() << ", error:" << _openssl->getErrMsg() << endl); return false; } } @@ -385,12 +390,12 @@ bool Transceiver::sendAuthData(const BasicAuthInfo& info) #endif - TLOGTARS("[TARS][sendAuthData:" << objPrx->name() << " len: " << _sendBuffer.getBufferLength() << endl); + TLOGTARS("[sendAuthData:" << objPrx->name() << " len: " << _sendBuffer.getBufferLength() << endl); int ret = doRequest(); if (ret != 0) { - TLOGERROR("[TARS][Transceiver::setConnected failed sendRequest for Auth\n"); + TLOGERROR("[Transceiver::setConnected failed sendRequest for Auth\n"); close(); return false; } @@ -401,10 +406,8 @@ bool Transceiver::sendAuthData(const BasicAuthInfo& info) void Transceiver::close() { if(!isValid()) return; -// if(_adapterProxy->getObjProxy()->getPushCallback()) -// { -// _adapterProxy->getObjProxy()->getPushCallback()->onClose(); -// } + + #if TARS_SSL if (_openssl) { @@ -427,7 +430,21 @@ void Transceiver::close() _authState = AUTH_INIT; - TLOGTARS("[TARS][trans close:"<< _adapterProxy->getObjProxy()->name()<< "," << _ep.desc() << "]" << endl); + if(_adapterProxy->getObjProxy()->getPushCallback()) + { + _adapterProxy->getObjProxy()->getPushCallback()->onClose(); + } + + int second = _adapterProxy->getObjProxy()->reconnect(); + + if(second > 0) { + _adapterProxy->getObjProxy()->getCommunicatorEpoll()->reConnect(TNOWMS + second * 1000, this); + TLOGERROR("[trans close:" << _adapterProxy->getObjProxy()->name() << "," << _ep.desc() << ", reconnect:" << second << "]" << endl); + } +// else +// { +// TLOGERROR("[trans close:" << _adapterProxy->getObjProxy()->name() << "," << _ep.desc() << "]" << endl); +// } } int Transceiver::doRequest() @@ -452,7 +469,7 @@ int Transceiver::doRequest() //取adapter里面积攒的数据 if(_sendBuffer.empty()) { - _adapterProxy->doInvoke(); + _adapterProxy->doInvoke(false); } //object里面应该是空的 @@ -479,7 +496,7 @@ int Transceiver::sendRequest(const shared_ptr &buff) if (isSSL() && !_openssl) return eRetError; #endif - TLOGTARS("[TARS][Transceiver::sendRequest failed, obj:" << _adapterProxy->getObjProxy()->name() << ", need auth." << endl); + TLOGTARS("[Transceiver::sendRequest failed, obj:" << _adapterProxy->getObjProxy()->name() << ", need auth." << endl); return eRetError; // 需要鉴权但还没通过,不能发送非认证消息 } @@ -494,14 +511,14 @@ int Transceiver::sendRequest(const shared_ptr &buff) if (isSSL()) { if(!_openssl->isHandshaked()) { - TLOGTARS("[TARS][Transceiver::sendRequest failed, obj:" << _adapterProxy->getObjProxy()->name() << ", ssl need handshake." << endl); + TLOGTARS("[Transceiver::sendRequest failed, obj:" << _adapterProxy->getObjProxy()->name() << ", ssl need handshake." << endl); return eRetError; } int ret = _openssl->write(buff->buffer(), (uint32_t) buff->length(), _sendBuffer); if(ret != 0) { - TLOGERROR("[TARS][Transceiver::sendRequest ssl write failed, obj:" << _adapterProxy->getObjProxy()->name() << ", error:" << _openssl->getErrMsg() << endl); + TLOGERROR("[Transceiver::sendRequest ssl write failed, obj:" << _adapterProxy->getObjProxy()->name() << ", error:" << _openssl->getErrMsg() << endl); return eRetError; } @@ -534,7 +551,7 @@ int Transceiver::sendRequest(const shared_ptr &buff) } #endif -// TLOGTARS("[TARS][Transceiver::sendRequest handshake:" << _openssl->isHandshaked() << ", origin length:" << buff->length() << endl); +// TLOGTARS("[Transceiver::sendRequest handshake:" << _openssl->isHandshaked() << ", origin length:" << buff->length() << endl); int iRet = this->send(buff->buffer(), (uint32_t)buff->length(), 0); @@ -583,13 +600,13 @@ int TcpTransceiver::doResponse() int ret = _openssl->read(buff, iRet, _sendBuffer); if (ret != 0) { - TLOGERROR("[TARS][Transceiver::doResponse SSL_read handshake failed: " << _adapterProxy->getObjProxy()->name() << ", info:" << _openssl->getErrMsg() << endl); + TLOGERROR("[Transceiver::doResponse SSL_read handshake failed: " << _adapterProxy->getObjProxy()->name() << ", info:" << _openssl->getErrMsg() << endl); close(); return -1; } else if(!_sendBuffer.empty()) { - TLOGTARS("[TARS][Transceiver::doResponse SSL_read prehandshake:" << preHandshake << ", handshake:" << _openssl->isHandshaked() << ", send handshake:" << _sendBuffer.getBufferLength() << endl); + TLOGTARS("[Transceiver::doResponse SSL_read prehandshake:" << preHandshake << ", handshake:" << _openssl->isHandshaked() << ", send handshake:" << _sendBuffer.getBufferLength() << endl); doRequest(); } @@ -623,7 +640,7 @@ int TcpTransceiver::doResponse() ret = _adapterProxy->getObjProxy()->getProxyProtocol().responseFunc(*rbuf, *rsp.get()); if (ret == TC_NetWorkBuffer::PACKET_ERR) { - TLOGERROR( "[TARS][tcp doResponse," << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "," << _ep.desc() << ",tcp recv decode error" << endl); + TLOGERROR( "[tcp doResponse," << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "," << _ep.desc() << ",tcp recv decode error" << endl); close(); break; } @@ -650,13 +667,13 @@ int TcpTransceiver::doResponse() } } catch (exception & ex) { - TLOGERROR("[TARS][tcp doResponse," << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "," + TLOGERROR("[tcp doResponse," << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "," << _ep.desc() << ",tcp recv decode error:" << ex.what() << endl); close(); } catch (...) { - TLOGERROR("[TARS][tcp doResponse," << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "," + TLOGERROR("[tcp doResponse," << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "," << _ep.desc() << ",tcp recv decode error." << endl); close(); @@ -665,7 +682,7 @@ int TcpTransceiver::doResponse() } while (iRet>0); -// TLOGTARS("[TARS][tcp doResponse, " << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << ", all recvbuf:" << _recvBuffer.getBufferLength() << "]" << endl); +// TLOGTARS("[tcp doResponse, " << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << ", all recvbuf:" << _recvBuffer.getBufferLength() << "]" << endl); return 0; } @@ -708,7 +725,7 @@ int TcpTransceiver::doResponse() // } // while (iRet>0); -// TLOGTARS("[TARS][tcp doResponse objname:" << _adapterProxy->getObjProxy()->name() +// TLOGTARS("[tcp doResponse objname:" << _adapterProxy->getObjProxy()->name() // << ",fd:" << _fd << ",recvbuf:" << _recvBuffer.ReadableSize() << "]" << endl); // if(!_recvBuffer.IsEmpty()) @@ -724,7 +741,7 @@ int TcpTransceiver::doResponse() // std::string out; // if (!_openssl->Read(_recvBuffer.ReadAddr(), _recvBuffer.ReadableSize(), out)) // { -// TLOGERROR("[TARS][SSL_connect Failed: " << _adapterProxy->getObjProxy()->name() << endl); +// TLOGERROR("[SSL_connect Failed: " << _adapterProxy->getObjProxy()->name() << endl); // this->close(); // return -1; // } @@ -778,14 +795,14 @@ int TcpTransceiver::doResponse() // } // catch (exception &ex) // { -// TLOGERROR("[TARS][tcp doResponse objname:" << _adapterProxy->getObjProxy()->name() +// TLOGERROR("[tcp doResponse objname:" << _adapterProxy->getObjProxy()->name() // << ",fd:" << _fd << ",desc:" << _ep.desc() << ",tcp recv decode error:" << ex.what() << endl); // close(); // } // catch (...) // { -// TLOGERROR("[TARS][tcp doResponse objname:" << _adapterProxy->getObjProxy()->name() +// TLOGERROR("[tcp doResponse objname:" << _adapterProxy->getObjProxy()->name() // << ",fd:" << _fd << ",desc" << _ep.desc() << ",tcp recv decode error." << endl); // close(); @@ -806,7 +823,7 @@ int TcpTransceiver::send(const void* buf, uint32_t len, uint32_t flag) if (iRet < 0 && !TC_Socket::isPending()) { - TLOGTARS("[TARS][tcp send," << _adapterProxy->getObjProxy()->name() << ", fd:" << _fd << "," << _ep.desc() + TLOGTARS("[tcp send," << _adapterProxy->getObjProxy()->name() << ", fd:" << _fd << "," << _ep.desc() << ", fail! errno:" << TC_Exception::getSystemCode() << ", " << TC_Exception::parseError(TC_Exception::getSystemCode()) << ", close]" << endl); @@ -821,7 +838,7 @@ int TcpTransceiver::send(const void* buf, uint32_t len, uint32_t flag) _adapterProxy->getObjProxy()->getCommunicatorEpoll()->modFd(_fd, &_fdInfo, EPOLLIN | EPOLLOUT); } #endif - TLOGTARS("[TARS][tcp send," << _adapterProxy->getObjProxy()->name() << ", fd:" << _fd << "," + TLOGTARS("[tcp send," << _adapterProxy->getObjProxy()->name() << ", fd:" << _fd << "," << _ep.desc() << ", len:" << iRet << "]" << endl); return iRet; @@ -837,7 +854,7 @@ int TcpTransceiver::send(const void* buf, uint32_t len, uint32_t flag) // if (iRet == 0 || (iRet < 0 && errno != EAGAIN)) // { -// TLOGTARS("[TARS][tcp readv, " << _adapterProxy->getObjProxy()->name() +// TLOGTARS("[tcp readv, " << _adapterProxy->getObjProxy()->name() // << ",fd:" << _fd << ", " << _ep.desc() <<",ret " << iRet // << ", fail! errno:" << errno << "," << strerror(errno) << ",close]" << endl); @@ -846,7 +863,7 @@ int TcpTransceiver::send(const void* buf, uint32_t len, uint32_t flag) // return 0; // } -// TLOGTARS("[TARS][tcp readv," << _adapterProxy->getObjProxy()->name() +// TLOGTARS("[tcp readv," << _adapterProxy->getObjProxy()->name() // << ",fd:" << _fd << "," << _ep.desc() << ",ret:" << iRet << "]" << endl); // return iRet; @@ -864,7 +881,7 @@ int TcpTransceiver::send(const void* buf, uint32_t len, uint32_t flag) // if (iRet == 0 || (iRet < 0 && errno != EAGAIN)) // { -// TLOGTARS("[TARS][tcp recv objname:" << _adapterProxy->getObjProxy()->name() +// TLOGTARS("[tcp recv objname:" << _adapterProxy->getObjProxy()->name() // << ",fd:" << _fd << ", " << _ep.desc() <<",ret " << iRet // << ", fail! errno:" << errno << "," << strerror(errno) << ",close]" << endl); @@ -873,7 +890,7 @@ int TcpTransceiver::send(const void* buf, uint32_t len, uint32_t flag) // return 0; // } -// TLOGTARS("[TARS][tcp recv objname:" << _adapterProxy->getObjProxy()->name() +// TLOGTARS("[tcp recv objname:" << _adapterProxy->getObjProxy()->name() // << ",fd:" << _fd << ",desc:" << _ep.desc() << ",ret:" << iRet << "]" << endl); // return iRet; @@ -890,7 +907,7 @@ int TcpTransceiver::recv(void* buf, uint32_t len, uint32_t flag) if (iRet == 0 || (iRet < 0 && !TC_Socket::isPending())) { - TLOGTARS("[TARS][tcp recv, " << _adapterProxy->getObjProxy()->name() + TLOGTARS("[tcp recv, " << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << ", " << _ep.desc() <<", ret:" << iRet << ", fail! errno:" << TC_Exception::getSystemCode() << "," << TC_Exception::parseError(TC_Exception::getSystemCode()) << ",close]" << endl); @@ -905,7 +922,7 @@ int TcpTransceiver::recv(void* buf, uint32_t len, uint32_t flag) _adapterProxy->getObjProxy()->getCommunicatorEpoll()->modFd(_fd, &_fdInfo, EPOLLIN | EPOLLOUT); } #endif - TLOGTARS("[TARS][tcp recv," << _adapterProxy->getObjProxy()->name() + TLOGTARS("[tcp recv," << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "," << _ep.desc() << ", len:" << iRet << "]" << endl); return iRet; @@ -924,7 +941,7 @@ UdpTransceiver::UdpTransceiver(AdapterProxy * pAdapterProxy, const EndpointInfo _pRecvBuffer = new char[DEFAULT_RECV_BUFFERSIZE]; if(!_pRecvBuffer) { - throw TC_Exception("objproxy '" + _adapterProxy->getObjProxy()->name() + "' malloc udp receive buffer fail"); + throw TC_Exception("obj: '" + _adapterProxy->getObjProxy()->name() + "' malloc udp receive buffer fail"); } } @@ -951,7 +968,7 @@ int UdpTransceiver::doResponse() { if ((recv = this->recv(_pRecvBuffer, DEFAULT_RECV_BUFFERSIZE, 0)) > 0) { - TLOGTARS("[TARS][udp doResponse, " << _adapterProxy->getObjProxy()->name() + TLOGTARS("[udp doResponse, " << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << ",recvbuf:" << recv << "]" << endl); _recvBuffer.clearBuffers(); @@ -967,7 +984,7 @@ int UdpTransceiver::doResponse() if(ret == TC_NetWorkBuffer::PACKET_ERR || ret == TC_NetWorkBuffer::PACKET_LESS) { - TLOGERROR("[TARS][udp doResponse," << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "," << _ep.desc() << ",tcp recv decode error, ret:" << ret << endl); + TLOGERROR("[udp doResponse," << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "," << _ep.desc() << ",tcp recv decode error, ret:" << ret << endl); break; } else @@ -977,13 +994,13 @@ int UdpTransceiver::doResponse() } catch (exception &ex) { - TLOGERROR("[TARS][udp doResponse, " << _adapterProxy->getObjProxy()->name() + TLOGERROR("[udp doResponse, " << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "," << _ep.desc() << ", udp recv decode error:" << ex.what() << endl); } catch (...) { - TLOGERROR("[TARS][udp doResponse, " << _adapterProxy->getObjProxy()->name() + TLOGERROR("[udp doResponse, " << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "," << _ep.desc() << ", udp recv decode error." << endl); } @@ -998,13 +1015,14 @@ int UdpTransceiver::send(const void* buf, uint32_t len, uint32_t flag) { if(!isValid()) return -1; - int iRet=::sendto(_fd, (const char*)buf, len, flag, (struct sockaddr*) &(_ep.addr()), sizeof(sockaddr)); + socklen_t addrlen = _ep.isIPv6() ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); + int iRet=::sendto(_fd, (const char*)buf, len, flag, _ep.addrPtr(), addrlen); if (iRet<0) { if(!TC_Socket::isPending()) { - TLOGERROR("[TARS][udp send " << _adapterProxy->getObjProxy()->name() + TLOGERROR("[udp send " << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "," << _ep.desc() << ", fail! errno:" << TC_Exception::getSystemCode() << "," << TC_Exception::parseError(TC_Exception::getSystemCode()) << ",close]" << endl); @@ -1017,7 +1035,7 @@ int UdpTransceiver::send(const void* buf, uint32_t len, uint32_t flag) } else if(iRet>0 && iRet != (int)len) { - TLOGERROR("[TARS][udp send, " << _adapterProxy->getObjProxy()->name() + TLOGERROR("[udp send, " << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "," << _ep.desc() << ", send error." << ", len:" << len << ", sendLen:" << iRet << endl); //udp只发一次 发送一半也算全部发送成功 @@ -1034,7 +1052,7 @@ int UdpTransceiver::recv(void* buf, uint32_t len, uint32_t flag) if (iRet < 0 && !TC_Socket::isPending()) { - TLOGERROR("[TARS][udp recv " << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "," + TLOGERROR("[udp recv " << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "," << _ep.desc() << ", fail! errno:" << TC_Exception::getSystemCode() << "," << TC_Exception::parseError(TC_Exception::getSystemCode()) << ",close]" << endl); @@ -1059,7 +1077,7 @@ int UdpTransceiver::recv(void* buf, uint32_t len, uint32_t flag) // { // if ((recv = this->recv(_recvBuffer, DEFAULT_RECV_BUFFERSIZE, 0)) > 0) // { -// TLOGTARS("[TARS][udp doResponse objname:" << _adapterProxy->getObjProxy()->name() +// TLOGTARS("[udp doResponse objname:" << _adapterProxy->getObjProxy()->name() // << ",fd:" << _fd << ",recvbuf:" << recv << "]" << endl); // try @@ -1068,13 +1086,13 @@ int UdpTransceiver::recv(void* buf, uint32_t len, uint32_t flag) // } // catch (exception &ex) // { -// TLOGERROR("[TARS][udp doResponse, " << _adapterProxy->getObjProxy()->name() +// TLOGERROR("[udp doResponse, " << _adapterProxy->getObjProxy()->name() // << ",fd:" << _fd << ",desc:" << _ep.desc() // << ", udp recv decode error:" << ex.what() << endl); // } // catch (...) // { -// TLOGERROR("[TARS][udp doResponse, " << _adapterProxy->getObjProxy()->name() +// TLOGERROR("[udp doResponse, " << _adapterProxy->getObjProxy()->name() // << ",fd:" << _fd << ",desc:" << _ep.desc() // << ", udp recv decode error." << endl); // } @@ -1098,7 +1116,7 @@ int UdpTransceiver::recv(void* buf, uint32_t len, uint32_t flag) // { // if(errno != EAGAIN) // { -// TLOGERROR("[TARS][udp send objname:" << _adapterProxy->getObjProxy()->name() +// TLOGERROR("[udp send objname:" << _adapterProxy->getObjProxy()->name() // << ",fd:" << _fd << ",desc:" << _ep.desc() // << ", fail! errno:" << errno << "," << strerror(errno) << ",close]" << endl); @@ -1111,7 +1129,7 @@ int UdpTransceiver::recv(void* buf, uint32_t len, uint32_t flag) // } // else if(iRet > 0 && iRet != (int)len) // { -// TLOGERROR("[TARS][udp send objname:" << _adapterProxy->getObjProxy()->name() +// TLOGERROR("[udp send objname:" << _adapterProxy->getObjProxy()->name() // << ",fd:" << _fd << "," << _ep.desc() << ", send error." // << ", len:" << len << ", sendLen:" << iRet << endl); @@ -1133,7 +1151,7 @@ int UdpTransceiver::recv(void* buf, uint32_t len, uint32_t flag) // if (iRet < 0 && errno != EAGAIN) // { -// TLOGERROR("[TARS][udp recv objname:" << _adapterProxy->getObjProxy()->name() +// TLOGERROR("[udp recv objname:" << _adapterProxy->getObjProxy()->name() // << ",fd:" << _fd << ",desc:" << _ep.desc() // << ", fail! errno:" << errno << "," << strerror(errno) << ",close]" << endl); diff --git a/servant/makefile/makefile.tars b/servant/makefile/makefile.tars index 36a91bed2efb4473c202572d47cb0c461c18686d..9a64ccb266205d20a2a428afe7c2ef201d4f9a3a 100644 --- a/servant/makefile/makefile.tars +++ b/servant/makefile/makefile.tars @@ -42,8 +42,8 @@ MYSQL_LIB_DIR += -L/usr/local/mysql/lib/mysql -L/usr/local/mysql/lib -L/usr/li LIB_DIR += ${MYSQL_LIB_DIR} INC_DIR += ${MYSQL_INC} -ifneq ($(_USE_OPENTRACKING), 0) -ifneq ($(_USE_OPENTRACKING), ) +ifneq ($(TARS_OPENTRACKING), 0) +ifneq ($(TARS_OPENTRACKING), ) OPENTRACKING_INC += -I/usr/local/include OPENTRACKING_LIB_DIR += -L/usr/local/lib LIB_DIR += ${OPENTRACKING_LIB_DIR} @@ -72,8 +72,8 @@ ifneq ($(TARS_HTTP2), ) endif endif -ifneq ($(_USE_OPENTRACKING), 0) -ifneq ($(_USE_OPENTRACKING), ) +ifneq ($(TARS_OPENTRACKING), 0) +ifneq ($(TARS_OPENTRACKING), ) #业务编译 CFLAGS += -D_USE_OPENTRACKING=1 LIB += -lopentracing -lzipkin_opentracing -lzipkin -lcurl diff --git a/servant/makefile/tars-tools.cmake b/servant/makefile/tars-tools.cmake new file mode 100755 index 0000000000000000000000000000000000000000..9103491312d2497abce24fc013385c81d72f3381 --- /dev/null +++ b/servant/makefile/tars-tools.cmake @@ -0,0 +1,284 @@ + +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +if(WIN32) + set(TARS2CPP "c:/tars/cpp/tools/tars2cpp.exe") + set(TARS_PATH "c:/tars/cpp") +else() + set(TARS2CPP "/usr/local/tars/cpp/tools/tars2cpp") + set(TARS_PATH "/usr/local/tars/cpp") +endif() + +if(APPLE) + link_libraries(iconv) +endif() + +IF (UNIX) + link_libraries(pthread dl) +ENDIF () + +set(TARS_INC "${TARS_PATH}/include") +set(TARS_LIB_DIR "${TARS_PATH}/lib" ) + +if(WIN32) + set (LIB_TARS_SERVANT "${TARS_LIB_DIR}/tarsservant.lib") + set (LIB_TARS_UTIL "${TARS_LIB_DIR}/tarsutil.lib") +else() + set (LIB_TARS_SERVANT "${TARS_LIB_DIR}/libtarsservant.a") + set (LIB_TARS_UTIL "${TARS_LIB_DIR}/libtarsutil.a") +endif() + +include_directories(${TARS_INC}) +link_directories(${TARS_LIB_DIR}) +include_directories(${TARS_PATH}/thirdparty/include/mysql) + +if(WIN32) + set(LIB_SSL "libssl") + set(LIB_CRYPTO "libcrypto") + set(LIB_MYSQL "libmysql") + set(LIB_HTTP2 "nghttp2_static") +else() + set(LIB_SSL "ssl") + set(LIB_CRYPTO "crypto") + set(LIB_MYSQL "mysqlclient") + set(LIB_HTTP2 "nghttp2_static") +endif () + +set(CMAKE_BUILD_TYPE "Release" CACHE STRING "set build type to release default") +IF (CMAKE_BUILD_TYPE STREQUAL "") + set(CMAKE_BUILD_TYPE "Release") +ENDIF () + +set(TARS_WEB_HOST "" CACHE STRING "set web host") +IF (TARS_WEB_HOST STREQUAL "") + set(TARS_WEB_HOST "http://web.tars.com") +ENDIF () + +set(TARS_TOKEN "" CACHE STRING "set web token") + +set(PLATFORM) +IF (UNIX) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -std=c++11 -Wno-deprecated -fno-strict-aliasing -Wno-overloaded-virtual") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-builtin-macro-redefined -D__FILE__='\"$(notdir $(abspath $<))\"'") + + set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -Wall -g") + set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O2 -Wall -fno-strict-aliasing") + + set(PLATFORM "linux") + IF (APPLE) + set(PLATFORM "mac") + SET(CMAKE_C_ARCHIVE_CREATE " Scr ") + SET(CMAKE_CXX_ARCHIVE_CREATE " Scr ") + SET(CMAKE_C_ARCHIVE_FINISH " -no_warning_for_no_symbols -c ") + SET(CMAKE_CXX_ARCHIVE_FINISH " -no_warning_for_no_symbols -c ") + ENDIF (APPLE) + +ELSEIF (WIN32) + set(PLATFORM "window") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4101 /wd4244 /wd4996 /wd4091 /wd4503 /wd4819 /wd4200 /wd4800 /wd4267") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /bigobj ") + +ELSE () + MESSAGE(STATUS "================ ERROR: This platform is unsupported!!! ================") +ENDIF (UNIX) + +set(TARS_RELEASE "${PROJECT_BINARY_DIR}/run-release.cmake") +set(TARS_UPLOAD "${PROJECT_BINARY_DIR}/run-upload.cmake") +set(TARS_TAR "${PROJECT_BINARY_DIR}/run-tar.cmake") + +FILE(WRITE ${TARS_RELEASE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E echo release all)\n") +FILE(WRITE ${TARS_UPLOAD} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E echo upload all)\n") +FILE(WRITE ${TARS_TAR} "") + +function(gen_tars TARGET) + + file(GLOB_RECURSE TARS_INPUT *.tars) + + set(OUT_TARS_H_LIST) + + if (TARS_INPUT) + + foreach(TARS_FILE ${TARS_INPUT}) + get_filename_component(TARS_NAME ${TARS_FILE} NAME_WE) + get_filename_component(TARS_PATH ${TARS_FILE} PATH) + + set(CUR_TARS_GEN ${TARS_PATH}/${TARS_NAME}.h) + + add_custom_command( + OUTPUT ${CUR_TARS_GEN} + WORKING_DIRECTORY ${TARS_PATH} + COMMAND ${TARS2CPP} ${TARS_TOOL_FLAG} ${TARS_FILE} + COMMENT "${TARS2CPP} ${TARS_TOOL_FLAG} ${TARS_FILE}" + DEPENDS ${TARS2CPP} ${TARS_FILE} + ) + + list(APPEND OUT_TARS_H_LIST ${CUR_TARS_GEN}) + + endforeach() + + add_custom_target(${TARGET} ALL DEPENDS ${OUT_TARS_H_LIST}) + + set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${OUT_TARS_H_LIST}") + + endif() + +endfunction() + +#生成带tars文件的可执行程序 +macro(gen_server APP TARGET) + + set(UPLOAD_FILES ${ARGN}) + + include_directories(${PROJECT_SOURCE_DIR}) + + FILE(GLOB_RECURSE SRC_FILES "*.cc" "*.cpp" "*.c") + + add_executable(${TARGET} ${SRC_FILES}) + file(GLOB_RECURSE TARS_INPUT *.tars) + + if(TARS_INPUT) + gen_tars(tars-${TARGET}) + add_dependencies(${TARGET} tars-${TARGET}) + endif() + + if(TARS_SSL) + target_link_libraries(${TARGET} ${LIB_SSL} ${LIB_CRYPTO}) + + if(WIN32) + target_link_libraries(${TARGET} Crypt32) + endif() + endif() + + if(TARS_HTTP2) + target_link_libraries(${TARGET} ${LIB_HTTP2}) + endif() + + target_link_libraries(${TARGET} ${LIB_TARS_SERVANT} ${LIB_TARS_UTIL}) + + #make tar ######################################################################### + #must create tmp directory, avoid linux cmake conflict! + SET(RUN_TAR_COMMAND_FILE "${CMAKE_BINARY_DIR}/run-tar-${TARGET}.cmake") + FILE(WRITE ${RUN_TAR_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E echo mkdir -p ${CMAKE_BINARY_DIR}/tmp/${TARGET})\n") + FILE(APPEND ${RUN_TAR_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E echo rm -rf ${CMAKE_BINARY_DIR}/tmp/${TARGET})\n") + FILE(APPEND ${RUN_TAR_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/tmp/${TARGET})\n") + + SET(TARGET_EXE_NAME ${TARGET}) + IF(WIN32) + SET(TARGET_EXE_NAME "${TARGET_EXE_NAME}.exe") + ENDIF() + + IF(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC) + FILE(APPEND ${RUN_TAR_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E echo copy bin/${CMAKE_BUILD_TYPE}/${TARGET_EXE_NAME} ${CMAKE_BINARY_DIR}/tmp/${TARGET}/)\n") + FILE(APPEND ${RUN_TAR_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy bin/${CMAKE_BUILD_TYPE}/${TARGET_EXE_NAME} ${CMAKE_BINARY_DIR}/tmp/${TARGET}/)\n") + ELSE() + FILE(APPEND ${RUN_TAR_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E echo copy bin/${TARGET_EXE_NAME} ${CMAKE_BINARY_DIR}/tmp/${TARGET}/)\n") + FILE(APPEND ${RUN_TAR_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy bin/${TARGET_EXE_NAME} ${CMAKE_BINARY_DIR}/tmp/${TARGET}/)\n") + ENDIF() + + foreach(UPLOAD ${UPLOAD_FILES}) + FILE(APPEND ${RUN_TAR_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E echo copy ${UPLOAD} ${CMAKE_BINARY_DIR}/tmp/${TARGET}/)\n") + IF(WIN32) + FILE(APPEND ${RUN_TAR_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy ${UPLOAD} ${CMAKE_BINARY_DIR}/tmp/${TARGET}/)\n") + ELSE() + FILE(APPEND ${RUN_TAR_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy ${UPLOAD} ${CMAKE_BINARY_DIR}/tmp/${TARGET}/)\n") + ENDIF() + endforeach(UPLOAD ${UPLOAD_FILES}) + + FILE(APPEND ${RUN_TAR_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_BINARY_DIR}/tmp/ tar czfv ${TARGET}.tgz ${TARGET})\n") + FILE(APPEND ${RUN_TAR_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/tmp/${TARGET}.tgz ${CMAKE_BINARY_DIR}/${TARGET}.tgz)\n") + + add_custom_command(OUTPUT ${TARGET}.tgz + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -P ${RUN_TAR_COMMAND_FILE} + COMMENT "call ${RUN_TAR_COMMAND_FILE}") + + add_custom_target(${TARGET}-tar DEPENDS ${TARGET}.tgz ${TARGET}) + + FILE(APPEND ${TARS_TAR} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -P ${RUN_TAR_COMMAND_FILE})\n") + + #make upload ######################################################################### + SET(RUN_UPLOAD_COMMAND_FILE "${PROJECT_BINARY_DIR}/run-upload-${TARGET}.cmake") + IF(WIN32) + FILE(WRITE ${RUN_UPLOAD_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E echo ${TARS_WEB_HOST}/api/upload_and_publish -Fsuse=@${TARGET}.tgz -Fapplication=${APP} -Fmodule_name=${TARGET} -Fcomment=developer-auto-upload)\n") + FILE(APPEND ${RUN_UPLOAD_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${TARS_PATH}/thirdparty/bin/curl.exe ${TARS_WEB_HOST}/api/upload_and_publish?ticket=${TARS_TOKEN} -Fsuse=@${TARGET}.tgz -Fapplication=${APP} -Fmodule_name=${TARGET} -Fcomment=developer-auto-upload)\n") + FILE(APPEND ${RUN_UPLOAD_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND -E echo \n---------------------------------------------------------------------------)\n") + ELSE() + FILE(WRITE ${RUN_UPLOAD_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E echo ${TARS_WEB_HOST}/api/upload_and_publish -Fsuse=@${TARGET}.tgz -Fapplication=${APP} -Fmodule_name=${TARGET} -Fcomment=developer-auto-upload)\n") + FILE(APPEND ${RUN_UPLOAD_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND curl ${TARS_WEB_HOST}/api/upload_and_publish?ticket=${TARS_TOKEN} -Fsuse=@${TARGET}.tgz -Fapplication=${APP} -Fmodule_name=${TARGET} -Fcomment=developer-auto-upload)\n") + FILE(APPEND ${RUN_UPLOAD_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E echo \n---------------------------------------------------------------------------)\n") + + ENDIF() + + #执行命令 + add_custom_target(${TARGET}-upload + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS ${TARGET}-tar + COMMAND cmake -P ${RUN_UPLOAD_COMMAND_FILE} + COMMENT "upload ${APP}.${TARGET}.tgz and publish...") + + FILE(APPEND ${TARS_UPLOAD} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -P ${RUN_UPLOAD_COMMAND_FILE})\n") + + #make release ######################################################################### + SET(RUN_RELEASE_COMMAND_FILE "${PROJECT_BINARY_DIR}/run-release-${TARGET}.cmake") + + if (TARS_INPUT) + foreach(TARS_FILE ${TARS_INPUT}) + get_filename_component(TARS_NAME ${TARS_FILE} NAME_WE) + get_filename_component(TARS_PATH ${TARS_FILE} PATH) + + set(CUR_TARS_GEN ${TARS_PATH}/${TARS_NAME}.h) + + if(WIN32) + FILE(WRITE ${RUN_RELEASE_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory c:\\tarsproto\\protocol\\${APP}\\${TARGET})\n") + FILE(APPEND ${RUN_RELEASE_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E echo cp -rf ${CUR_TARS_GEN} c:\\tarsproto\\protocol\\${APP}\\${TARGET})\n") + FILE(APPEND ${RUN_RELEASE_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy ${CUR_TARS_GEN} c:\\tarsproto\\protocol\\${APP}\\${TARGET})\n") + elseif(APPLE) + FILE(WRITE ${RUN_RELEASE_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory $ENV{HOME}/tarsproto/protocol/${APP}/${TARGET})\n") + FILE(APPEND ${RUN_RELEASE_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E echo cp -rf ${CUR_TARS_GEN} $ENV{HOME}/tarsproto/protocol/${APP}/${TARGET})\n") + FILE(APPEND ${RUN_RELEASE_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy ${CUR_TARS_GEN} $ENV{HOME}/tarsproto/protocol/${APP}/${TARGET})\n") + elseif(UNIX) + FILE(WRITE ${RUN_RELEASE_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory /home/tarsproto/${APP}/${TARGET})\n") + FILE(APPEND ${RUN_RELEASE_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E echo cp -rf ${CUR_TARS_GEN} /home/tarsproto/${APP}/${TARGET})\n") + FILE(APPEND ${RUN_RELEASE_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy ${CUR_TARS_GEN} /home/tarsproto/${APP}/${TARGET})\n") + endif() + endforeach(TARS_FILE ${TARS_INPUT}) + + add_custom_target(${TARGET}-release + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS ${TARGET} + COMMAND cmake -P ${RUN_RELEASE_COMMAND_FILE} + COMMENT "call ${RUN_RELEASE_COMMAND_FILE}") + + FILE(APPEND ${TARS_RELEASE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -P ${RUN_RELEASE_COMMAND_FILE})\n") + endif () +endmacro() + +add_custom_target(upload + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMAND cmake -P ${TARS_UPLOAD}) + +add_custom_target(release + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMAND cmake -P ${TARS_RELEASE}) + +add_custom_target(tar + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMAND cmake -P ${TARS_TAR}) + +message("-------------------------------------------------------------------------------------") +message("CMAKE_SOURCE_DIR: ${CMAKE_SOURCE_DIR}") +message("CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}") +message("PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}") +message("CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") +message("PLATFORM: ${PLATFORM}") +message("TARS2CPP: ${TARS2CPP}") +message("TARS_MYSQL: ${TARS_MYSQL}") +message("TARS_HTTP2: ${TARS_HTTP2}") +message("TARS_SSL: ${TARS_SSL}") +message("TARS_WEB_HOST: ${TARS_WEB_HOST}") +message("TARS_TOKEN: ${TARS_TOKEN}") +message("-------------------------------------------------------------------------------------") + diff --git a/servant/protocol b/servant/protocol index b84624baa43088b77e7bb016bc833027a6d9f219..790bef8cbc1ba2c1b9adabf9a68ab322b9a3a119 160000 --- a/servant/protocol +++ b/servant/protocol @@ -1 +1 @@ -Subproject commit b84624baa43088b77e7bb016bc833027a6d9f219 +Subproject commit 790bef8cbc1ba2c1b9adabf9a68ab322b9a3a119 diff --git a/servant/script/cmake_demo/CMakeLists.txt b/servant/script/cmake_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..38c1c11aacab4ffff30c0e524f3bc398dd113297 --- /dev/null +++ b/servant/script/cmake_demo/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 2.8) + +project(Demo-DemoServer) + +option(TARS_MYSQL "option for mysql" ON) +option(TARS_SSL "option for ssl" OFF) +option(TARS_HTTP2 "option for http2" OFF) + +if(WIN32) + include (c:\\tars\\cpp\\makefile\\tars-tools.cmake) +else() + include (/usr/local/tars/cpp/makefile/tars-tools.cmake) +endif() + +####you can: cd build; cmake .. -DTARS_WEB_HOST={your web host} +set(TARS_WEB_HOST "" CACHE STRING "set web host") +IF (TARS_WEB_HOST STREQUAL "") + set(TARS_WEB_HOST "http://tars.test.com") +ENDIF () + +include_directories(/usr/local/tars/cpp/thirdparty/include) +link_directories(/usr/local/tars/cpp/thirdparty/lib) + +#include_directories(/home/tarsprotol/App/OtherServer) + +add_subdirectory(src) + +#target_link_libraries(mysqlclient ssl crypto nghttp2-static) diff --git a/servant/script/cmake_demo/src/CMakeLists.txt b/servant/script/cmake_demo/src/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..59ebb2b7fe0a299bcb9e14ec9d2f60c008c1593c --- /dev/null +++ b/servant/script/cmake_demo/src/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 2.8) + +project(DemoApp-DemoServer) + +gen_server(DemoApp DemoServer) + +#target_link_libraries(mysqlclient ssl crypto nghttp2-static) diff --git a/servant/script/cmake_demo/src/DemoServant.tars b/servant/script/cmake_demo/src/DemoServant.tars new file mode 100644 index 0000000000000000000000000000000000000000..87f191010d9b2503bbe97035663f9d01fdc6ab54 --- /dev/null +++ b/servant/script/cmake_demo/src/DemoServant.tars @@ -0,0 +1,10 @@ + +module DemoApp +{ + +interface DemoServant +{ + int test(); +}; + +}; diff --git a/servant/script/cmake_demo/src/DemoServantImp.cpp b/servant/script/cmake_demo/src/DemoServantImp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c5ca8bc4268b5604dabf85c962eb21a12f15b247 --- /dev/null +++ b/servant/script/cmake_demo/src/DemoServantImp.cpp @@ -0,0 +1,19 @@ +#include "DemoServantImp.h" +#include "servant/Application.h" + +using namespace std; + +////////////////////////////////////////////////////// +void DemoServantImp::initialize() +{ + //initialize servant here: + //... +} + +////////////////////////////////////////////////////// +void DemoServantImp::destroy() +{ + //destroy servant here: + //... +} + diff --git a/servant/script/cmake_demo/src/DemoServantImp.h b/servant/script/cmake_demo/src/DemoServantImp.h new file mode 100644 index 0000000000000000000000000000000000000000..1f10d1b889bd3d7fe6c2378bf27ebf785775dd4a --- /dev/null +++ b/servant/script/cmake_demo/src/DemoServantImp.h @@ -0,0 +1,35 @@ +#ifndef _DemoServantImp_H_ +#define _DemoServantImp_H_ + +#include "servant/Application.h" +#include "DemoServant.h" + +/** + * + * + */ +class DemoServantImp : public DemoApp::DemoServant +{ +public: + /** + * + */ + virtual ~DemoServantImp() {} + + /** + * + */ + virtual void initialize(); + + /** + * + */ + virtual void destroy(); + + /** + * + */ + virtual int test(tars::TarsCurrentPtr current) { return 0;}; +}; +///////////////////////////////////////////////////// +#endif diff --git a/servant/script/cmake_demo/src/DemoServer.cpp b/servant/script/cmake_demo/src/DemoServer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c1ad88f4507f2801f2f00288894ad6445b930f01 --- /dev/null +++ b/servant/script/cmake_demo/src/DemoServer.cpp @@ -0,0 +1,43 @@ +#include "DemoServer.h" +#include "DemoServantImp.h" + +using namespace std; + +DemoServer g_app; + +///////////////////////////////////////////////////////////////// +void +DemoServer::initialize() +{ + //initialize application here: + //... + + addServant(ServerConfig::Application + "." + ServerConfig::ServerName + ".DemoServantObj"); +} +///////////////////////////////////////////////////////////////// +void +DemoServer::destroyApp() +{ + //destroy application here: + //... +} +///////////////////////////////////////////////////////////////// +int +main(int argc, char* argv[]) +{ + try + { + g_app.main(argc, argv); + g_app.waitForShutdown(); + } + catch (std::exception& e) + { + cerr << "std::exception:" << e.what() << std::endl; + } + catch (...) + { + cerr << "unknown exception." << std::endl; + } + return -1; +} +///////////////////////////////////////////////////////////////// diff --git a/servant/script/cmake_demo/src/DemoServer.h b/servant/script/cmake_demo/src/DemoServer.h new file mode 100644 index 0000000000000000000000000000000000000000..462c9661ed8c02d37fe6c89ce5e0f1f2697160ed --- /dev/null +++ b/servant/script/cmake_demo/src/DemoServer.h @@ -0,0 +1,34 @@ +#ifndef _DemoServer_H_ +#define _DemoServer_H_ + +#include +#include "servant/Application.h" + +using namespace tars; + +/** + * + **/ +class DemoServer : public Application +{ +public: + /** + * + **/ + virtual ~DemoServer() {}; + + /** + * + **/ + virtual void initialize(); + + /** + * + **/ + virtual void destroyApp(); +}; + +extern DemoServer g_app; + +//////////////////////////////////////////// +#endif diff --git a/servant/script/cmake_http_demo/CMakeLists.txt b/servant/script/cmake_http_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..38c1c11aacab4ffff30c0e524f3bc398dd113297 --- /dev/null +++ b/servant/script/cmake_http_demo/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 2.8) + +project(Demo-DemoServer) + +option(TARS_MYSQL "option for mysql" ON) +option(TARS_SSL "option for ssl" OFF) +option(TARS_HTTP2 "option for http2" OFF) + +if(WIN32) + include (c:\\tars\\cpp\\makefile\\tars-tools.cmake) +else() + include (/usr/local/tars/cpp/makefile/tars-tools.cmake) +endif() + +####you can: cd build; cmake .. -DTARS_WEB_HOST={your web host} +set(TARS_WEB_HOST "" CACHE STRING "set web host") +IF (TARS_WEB_HOST STREQUAL "") + set(TARS_WEB_HOST "http://tars.test.com") +ENDIF () + +include_directories(/usr/local/tars/cpp/thirdparty/include) +link_directories(/usr/local/tars/cpp/thirdparty/lib) + +#include_directories(/home/tarsprotol/App/OtherServer) + +add_subdirectory(src) + +#target_link_libraries(mysqlclient ssl crypto nghttp2-static) diff --git a/servant/script/cmake_http_demo/src/CMakeLists.txt b/servant/script/cmake_http_demo/src/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..61d91e5fdb4d6de91acd0fef5c55376509390f6a --- /dev/null +++ b/servant/script/cmake_http_demo/src/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 2.8) + +project(DemoApp-DemoServer) + +gen_server(DemoApp DemoServer) diff --git a/servant/script/cmake_http_demo/src/DemoServantImp.cpp b/servant/script/cmake_http_demo/src/DemoServantImp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0ac5668901d655705f16f5350b51d3a42ba58d5c --- /dev/null +++ b/servant/script/cmake_http_demo/src/DemoServantImp.cpp @@ -0,0 +1,44 @@ +#include "DemoServantImp.h" +#include "servant/Application.h" + +using namespace std; + +////////////////////////////////////////////////////// +void DemoServantImp::initialize() +{ + //initialize servant here: + //... +} + +////////////////////////////////////////////////////// +void DemoServantImp::destroy() +{ + //destroy servant here: + //... +} + +int DemoServantImp::doRequest(TarsCurrentPtr current, vector &buffer) +{ + TC_HttpRequest req; + TC_HttpResponse rsp; + + // parse request header + vector v = current->getRequestBuffer(); + string sBuf; + sBuf.assign(v.data(), v.size()); + req.decode(sBuf); + + int ret = doRequest(req, rsp); + + rsp.encode(buffer); + + return ret; +} + +int DemoServantImp::doRequest(const TC_HttpRequest &req, TC_HttpResponse &rsp) +{ + string msg = "Hello Tars!"; + rsp.setContentType("text/html"); + rsp.setResponse(msg.c_str(), msg.size()); + return 0; +} diff --git a/servant/script/cmake_http_demo/src/DemoServantImp.h b/servant/script/cmake_http_demo/src/DemoServantImp.h new file mode 100644 index 0000000000000000000000000000000000000000..5a5e9645a66e7cbdad8b58eab6d5e6d7e7041b41 --- /dev/null +++ b/servant/script/cmake_http_demo/src/DemoServantImp.h @@ -0,0 +1,37 @@ +#ifndef _DemoServantImp_H_ +#define _DemoServantImp_H_ + +#include "servant/Application.h" + +/** + * + * + */ +class DemoServantImp : public Servant +{ +public: + /** + * + */ + virtual ~DemoServantImp() {} + + /** + * + */ + virtual void initialize(); + + /** + * + */ + virtual void destroy(); + + /** + * + */ + int doRequest(TarsCurrentPtr current, vector &buffer); + +private: + int doRequest(const TC_HttpRequest &req, TC_HttpResponse &rsp); +}; +///////////////////////////////////////////////////// +#endif diff --git a/servant/script/cmake_http_demo/src/DemoServer.cpp b/servant/script/cmake_http_demo/src/DemoServer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d5208df6a5a21aaff160cea0483a6dd2bfcc291c --- /dev/null +++ b/servant/script/cmake_http_demo/src/DemoServer.cpp @@ -0,0 +1,44 @@ +#include "DemoServer.h" +#include "DemoServantImp.h" + +using namespace std; + +DemoServer g_app; + +///////////////////////////////////////////////////////////////// +void +DemoServer::initialize() +{ + //initialize application here: + //... + + addServant(ServerConfig::Application + "." + ServerConfig::ServerName + ".DemoServantObj"); + addServantProtocol(ServerConfig::Application + "." + ServerConfig::ServerName + ".DemoServantObj", &TC_NetWorkBuffer::parseHttp); +} +///////////////////////////////////////////////////////////////// +void +DemoServer::destroyApp() +{ + //destroy application here: + //... +} +///////////////////////////////////////////////////////////////// +int +main(int argc, char* argv[]) +{ + try + { + g_app.main(argc, argv); + g_app.waitForShutdown(); + } + catch (std::exception& e) + { + cerr << "std::exception:" << e.what() << std::endl; + } + catch (...) + { + cerr << "unknown exception." << std::endl; + } + return -1; +} +///////////////////////////////////////////////////////////////// diff --git a/servant/script/cmake_http_demo/src/DemoServer.h b/servant/script/cmake_http_demo/src/DemoServer.h new file mode 100644 index 0000000000000000000000000000000000000000..462c9661ed8c02d37fe6c89ce5e0f1f2697160ed --- /dev/null +++ b/servant/script/cmake_http_demo/src/DemoServer.h @@ -0,0 +1,34 @@ +#ifndef _DemoServer_H_ +#define _DemoServer_H_ + +#include +#include "servant/Application.h" + +using namespace tars; + +/** + * + **/ +class DemoServer : public Application +{ +public: + /** + * + **/ + virtual ~DemoServer() {}; + + /** + * + **/ + virtual void initialize(); + + /** + * + **/ + virtual void destroyApp(); +}; + +extern DemoServer g_app; + +//////////////////////////////////////////// +#endif diff --git a/servant/script/cmake_http_server.bat b/servant/script/cmake_http_server.bat new file mode 100644 index 0000000000000000000000000000000000000000..d56352044e7699d915f17cd7cc6c0c49cc6a51c2 --- /dev/null +++ b/servant/script/cmake_http_server.bat @@ -0,0 +1 @@ +c:\\tars\\cpp\\script\\busybox.exe bash c:\\tars\\cpp\\script\\cmake_http_server.sh %1 %2 %3 c:/tars \ No newline at end of file diff --git a/servant/script/win_create.bat b/servant/script/cmake_http_server.sh old mode 100644 new mode 100755 similarity index 57% rename from servant/script/win_create.bat rename to servant/script/cmake_http_server.sh index ed2afa05c23bbaafa1051cf7d17943afb4330ae0..a048578ac07f45ac70ec19f4ab146113d0976c65 --- a/servant/script/win_create.bat +++ b/servant/script/cmake_http_server.sh @@ -10,32 +10,37 @@ APP=$1 SERVER=$2 SERVANT=$3 +echo "APP:$APP, SERVER:$SERVER, SERVANT:$SERVANT" + if [ "$SERVER" == "$SERVANT" ] then echo "Error!(ServerName == ServantName)" exit -1 fi -if [ ! -d $APP/$SERVER/src ] +if [ ! -d $SERVER ] then - echo "[mkdir: $APP/$SERVER/src]" - mkdir -p $APP/$SERVER/src - echo "[mkdir: $APP/$SERVER/build]" - mkdir -p $APP/$SERVER/build + echo "[mkdir: $SERVER]" + mkdir -p $SERVER fi echo "[create server: $APP.$SERVER ...]" -DEMO_PATH=c:\\taf\\cpp\\script\\demo +TARSPATH=$4 -SRC_FILE="DemoServer.h DemoServer.cpp DemoServantImp.h DemoServantImp.cpp DemoServant.jce makefile CMakeLists.txt" +if [ "$TARSPATH" == "" ]; then + TARSPATH=/usr/local/tars +fi -for FILE in $SRC_FILE -do - cp -rf $DEMO_PATH\\$FILE $APP\\$SERVER\\src -done +DEMO_PATH=${TARSPATH}/cpp/script/cmake_http_demo + +#make cleanall -C $DEMO_PATH -cd $APP\\$SERVER\\src +cp -rf $DEMO_PATH/* $SERVER/ + +cd $SERVER/src + +SRC_FILE="DemoServer.h DemoServer.cpp DemoServantImp.h DemoServantImp.cpp CMakeLists.txt" for FILE in $SRC_FILE do @@ -44,7 +49,7 @@ do cat $FILE | sed "s/DemoApp/$APP/g" > $FILE.tmp mv $FILE.tmp $FILE - + cat $FILE | sed "s/DemoServant/$SERVANT/g" > $FILE.tmp mv $FILE.tmp $FILE done @@ -53,10 +58,12 @@ mv DemoServer.h ${SERVER}.h mv DemoServer.cpp ${SERVER}.cpp mv DemoServantImp.h ${SERVANT}Imp.h mv DemoServantImp.cpp ${SERVANT}Imp.cpp -mv DemoServant.jce ${SERVANT}.jce -cd ..\\build -cmake ..\\src -G "Visual Studio 14 2015 Win64" -DCMAKE_BUILD_TYPE=Debug -cmake ..\\src -G "Visual Studio 14 2015 Win64" -DCMAKE_BUILD_TYPE=Release +cd .. +mkdir build; cd build +cmake .. +cmake --build . --config Release + +#cd ../../ echo "[done.]" diff --git a/servant/script/cmake_tars_server.bat b/servant/script/cmake_tars_server.bat new file mode 100644 index 0000000000000000000000000000000000000000..d5d91651ff026849cf15433deb67a5b138b1ac02 --- /dev/null +++ b/servant/script/cmake_tars_server.bat @@ -0,0 +1 @@ +c:\\tars\\cpp\\script\\busybox.exe bash c:\\tars\\cpp\\script\\cmake_tars_server.sh %1 %2 %3 c:/tars diff --git a/servant/script/cmake_tars_server.sh b/servant/script/cmake_tars_server.sh new file mode 100755 index 0000000000000000000000000000000000000000..0f17e0b96fe3918bec0e753687858a4ed70f094d --- /dev/null +++ b/servant/script/cmake_tars_server.sh @@ -0,0 +1,71 @@ +#!/bin/sh + +if [ $# -lt 3 ] +then + echo "" + exit 0 +fi + +APP=$1 +SERVER=$2 +SERVANT=$3 + +echo "APP:$APP, SERVER:$SERVER, SERVANT:$SERVANT" + +TARSPATH=$4 + +if [ "$TARSPATH" == "" ]; then + TARSPATH=/usr/local/tars/ +fi + +if [ "$SERVER" == "$SERVANT" ] +then + echo "Error!(ServerName == ServantName)" + exit -1 +fi + +if [ ! -d $SERVER ] +then + echo "[mkdir: $SERVER]" + mkdir -p $SERVER +fi + +echo "[create server: $APP.$SERVER ...]" + +DEMO_PATH=${TARSPATH}/cpp/script/cmake_demo + +#make cleanall -C $DEMO_PATH + +cp -rf $DEMO_PATH/* $SERVER/ + +cd $SERVER/src + +SRC_FILE="DemoServer.h DemoServer.cpp DemoServantImp.h DemoServantImp.cpp DemoServant.tars CMakeLists.txt" + +for FILE in $SRC_FILE +do + cat $FILE | sed "s/DemoServer/$SERVER/g" > $FILE.tmp + mv $FILE.tmp $FILE + + cat $FILE | sed "s/DemoApp/$APP/g" > $FILE.tmp + mv $FILE.tmp $FILE + + cat $FILE | sed "s/DemoServant/$SERVANT/g" > $FILE.tmp + mv $FILE.tmp $FILE +done + +mv DemoServer.h ${SERVER}.h +mv DemoServer.cpp ${SERVER}.cpp +mv DemoServantImp.h ${SERVANT}Imp.h +mv DemoServantImp.cpp ${SERVANT}Imp.cpp +mv DemoServant.tars ${SERVANT}.tars + +cd .. +mkdir build; cd build +cmake .. +cmake --build . --config Release + + +#cd ../../ + +echo "[done.]" diff --git a/servant/script/create_http_server.sh b/servant/script/create_http_server.sh index 230b0ca19329edb326003f004b7acb8b2e3d21c4..1b60c0deb9dfa54609f33f2b0ed9290c918c6cac 100755 --- a/servant/script/create_http_server.sh +++ b/servant/script/create_http_server.sh @@ -9,6 +9,11 @@ fi APP=$1 SERVER=$2 SERVANT=$3 +TARSPATH=$4 + +if [ "$TARSPATH" == "" ]; then + TARSPATH=/usr/local/tars/ +fi if [ "$SERVER" == "$SERVANT" ] then @@ -24,7 +29,7 @@ fi echo "[create server: $APP.$SERVER ...]" -DEMO_PATH=/usr/local/tars/cpp/script/http_demo +DEMO_PATH=${TARSPATH}/cpp/script/http_demo cp $DEMO_PATH/* $APP/$SERVER/ @@ -39,7 +44,7 @@ do cat $FILE | sed "s/DemoApp/$APP/g" > $FILE.tmp mv $FILE.tmp $FILE - + cat $FILE | sed "s/DemoServant/$SERVANT/g" > $FILE.tmp mv $FILE.tmp $FILE done @@ -49,4 +54,4 @@ rename "DemoServant" "$SERVANT" $SRC_FILE cd ../../ -echo "[done.]" +echo "[done.]" \ No newline at end of file diff --git a/servant/script/create_tars_server.bat b/servant/script/create_tars_server.bat deleted file mode 100644 index 4b34347f46e550add222500ecbf01b60b8a84b5d..0000000000000000000000000000000000000000 --- a/servant/script/create_tars_server.bat +++ /dev/null @@ -1 +0,0 @@ -c:\\taf\\cpp\\script\\busybox.exe bash c:\\taf\\cpp\\script\\win_create.bat %1 %2 %3 diff --git a/servant/script/create_tars_server.sh b/servant/script/create_tars_server.sh old mode 100644 new mode 100755 index 0acee5d74ee6621feb9d14a1ba7d7b3dd6f83e49..f2db87852bc87376d5c1475e9c2f164af2a47207 --- a/servant/script/create_tars_server.sh +++ b/servant/script/create_tars_server.sh @@ -10,25 +10,29 @@ APP=$1 SERVER=$2 SERVANT=$3 +echo "APP:$APP, SERVER:$SERVER, SERVANT:$SERVANT" + if [ "$SERVER" == "$SERVANT" ] then echo "Error!(ServerName == ServantName)" exit -1 fi -if [ ! -d $APP/$SERVER ] +if [ ! -d $SERVER ] then - echo "[mkdir: $APP/$SERVER]" - mkdir -p $APP/$SERVER + echo "[mkdir: $SERVER]" + mkdir -p $SERVER fi echo "[create server: $APP.$SERVER ...]" DEMO_PATH=/usr/local/tars/cpp/script/demo -cp $DEMO_PATH/* $APP/$SERVER/ +#make cleanall -C $DEMO_PATH + +cp -rf $DEMO_PATH/* $SERVER/ -cd $APP/$SERVER/ +cd $SERVER SRC_FILE="DemoServer.h DemoServer.cpp DemoServantImp.h DemoServantImp.cpp DemoServant.tars makefile" @@ -39,14 +43,17 @@ do cat $FILE | sed "s/DemoApp/$APP/g" > $FILE.tmp mv $FILE.tmp $FILE - + cat $FILE | sed "s/DemoServant/$SERVANT/g" > $FILE.tmp mv $FILE.tmp $FILE done -rename "DemoServer" "$SERVER" $SRC_FILE -rename "DemoServant" "$SERVANT" $SRC_FILE +mv DemoServer.h ${SERVER}.h +mv DemoServer.cpp ${SERVER}.cpp +mv DemoServantImp.h ${SERVANT}Imp.h +mv DemoServantImp.cpp ${SERVANT}Imp.cpp +mv DemoServant.tars ${SERVANT}.tars -cd ../../ +make echo "[done.]" diff --git a/servant/script/demo/makefile b/servant/script/demo/makefile index 50d831d2eae1304464ca761b6e7ac385813d8d35..5c27a5cd3b62ffc3d023dfb2754a6edded844398 100644 --- a/servant/script/demo/makefile +++ b/servant/script/demo/makefile @@ -1,17 +1,16 @@ - #----------------------------------------------------------------------- APP := DemoApp TARGET := DemoServer -CONFIG := +CONFIG := STRIP_FLAG:= N -TARS2CPP_FLAG:= +TARS2CPP_FLAG:= -INCLUDE += -LIB += +INCLUDE += +LIB += #----------------------------------------------------------------------- include /usr/local/tars/cpp/makefile/makefile.tars -#----------------------------------------------------------------------- +#----------------------------------------------------------------------- \ No newline at end of file diff --git a/servant/script/http_demo/DemoServer.cpp b/servant/script/http_demo/DemoServer.cpp index 522ebc3c11a8a7519f8bf9e68c7746d171728952..d5208df6a5a21aaff160cea0483a6dd2bfcc291c 100644 --- a/servant/script/http_demo/DemoServer.cpp +++ b/servant/script/http_demo/DemoServer.cpp @@ -5,44 +5,6 @@ using namespace std; DemoServer g_app; -struct HttpProtocol -{ - /** - * 解析http请求 - * @param in - * @param out - * - * @return int - */ - static int parseHttp(string &in, string &out) - { - try - { - //判断请求是否是HTTP请求 - bool b = TC_HttpRequest ::checkRequest(in.c_str(), in.length()); - //完整的HTTP请求 - if(b) - { - out = in; - in = ""; - //TLOGDEBUG("out size: " << out.size() << endl); - return TC_EpollServer::PACKET_FULL; - } - else - { - return TC_EpollServer::PACKET_LESS; - } - } - catch(exception &ex) - { - return TC_EpollServer::PACKET_ERR; - } - - return TC_EpollServer::PACKET_LESS; //表示收到的包不完全 - } - -}; - ///////////////////////////////////////////////////////////////// void DemoServer::initialize() @@ -51,7 +13,7 @@ DemoServer::initialize() //... addServant(ServerConfig::Application + "." + ServerConfig::ServerName + ".DemoServantObj"); - addServantProtocol(ServerConfig::Application + "." + ServerConfig::ServerName + ".DemoServantObj", &HttpProtocol::parseHttp); + addServantProtocol(ServerConfig::Application + "." + ServerConfig::ServerName + ".DemoServantObj", &TC_NetWorkBuffer::parseHttp); } ///////////////////////////////////////////////////////////////// void diff --git a/servant/script/http_demo/makefile b/servant/script/http_demo/makefile index 50d831d2eae1304464ca761b6e7ac385813d8d35..5c27a5cd3b62ffc3d023dfb2754a6edded844398 100644 --- a/servant/script/http_demo/makefile +++ b/servant/script/http_demo/makefile @@ -1,17 +1,16 @@ - #----------------------------------------------------------------------- APP := DemoApp TARGET := DemoServer -CONFIG := +CONFIG := STRIP_FLAG:= N -TARS2CPP_FLAG:= +TARS2CPP_FLAG:= -INCLUDE += -LIB += +INCLUDE += +LIB += #----------------------------------------------------------------------- include /usr/local/tars/cpp/makefile/makefile.tars -#----------------------------------------------------------------------- +#----------------------------------------------------------------------- \ No newline at end of file diff --git a/servant/servant/AdapterProxy.h b/servant/servant/AdapterProxy.h index a2d11c5529b968f8c24c41e46fec4be84ddaaeb6..21ff424e62b76de3f7e9af8587b11321ad0d27d2 100644 --- a/servant/servant/AdapterProxy.h +++ b/servant/servant/AdapterProxy.h @@ -26,7 +26,9 @@ #include "servant/Message.h" #include "servant/StatReport.h" #include -#ifdef _USE_OPENTRACKING +#include + +#ifdef TARS_OPENTRACKING #include #endif namespace tars @@ -52,14 +54,30 @@ public: /** * 调用server端对象方法 + * @param req + * @return int */ - int invoke(ReqMessage * msg); + int invoke(ReqMessage * msg); + +// /** +// * 同步阻塞调用server +// * @param msg +// * @return +// */ +// bool invoke_sync(ReqMessage * msg); + + /** + * + */ + void onConnect(); /** * 发送请求 * 发送挤压的数据 + * @param req + * @return */ - void doInvoke(); + void doInvoke(bool initInvoke); /** * server端的响应包返回 @@ -91,9 +109,9 @@ public: /** * 处理采样 */ - void sample(ReqMessage * msg); +// void sample(ReqMessage * msg); -#ifdef _USE_OPENTRACKING +#ifdef TARS_OPENTRACKING /** * Zipkin调用链 */ @@ -169,6 +187,17 @@ public: */ inline int getId() const { return _id; } + /** + * + * @return + */ + inline Transceiver* getTransceiver() const { return _trans.get(); } + + /** + * 屏蔽结点 + */ + void onSetInactive(); + private: /** @@ -204,9 +233,31 @@ private: void merge(const StatMicMsgBody& inBody, StatMicMsgBody& outBody); /** - * 获取被调名 + * 连接串行模式 + * @param msg + * @return */ - string getSlaveName(const string& sSlaveName); + int invoke_connection_serial(ReqMessage * msg); + + /** + * 连接并行模式 + * @param msg + * @return + */ + int invoke_connection_parallel(ReqMessage * msg); + + void finishInvoke_serial(shared_ptr & rsp); + + void finishInvoke_parallel(shared_ptr & rsp); + + void doInvoke_serial(); + + void doInvoke_parallel(); + + /** + * 获取被调名 + */ + string getSlaveName(const string& sSlaveName); private: @@ -225,6 +276,11 @@ private: */ EndpointInfo _endpoint; + /** + * in request + */ + ReqMessage* _requestMsg = NULL; + /* * 收发包处理 */ @@ -315,20 +371,10 @@ private: */ map _statBody; - /* - * 最大采样次数 - */ - uint32_t _maxSampleCount; - - /* - * 采样比率 - */ - int _sampleRate; - /* * 调用链信息 */ -#ifdef _USE_OPENTRACKING +#ifdef TARS_OPENTRACKING map> _spanMap; #endif int _id; diff --git a/servant/servant/AdminServant.h b/servant/servant/AdminServant.h index 5ba422623651967fbbc7d5d9414957af02372397..3eec5083299b1927cf0e4722605401e6f7839877 100644 --- a/servant/servant/AdminServant.h +++ b/servant/servant/AdminServant.h @@ -22,7 +22,7 @@ namespace tars { -class TarsCurrent; +class Current; class Application; //////////////////////////////////////////////////////////////////////// diff --git a/servant/servant/AppCache.h b/servant/servant/AppCache.h index b58232c8564d905e9f64158e5646df50b49bf669..b974dc5097c199683d25158cc3d4883d03ed23a2 100644 --- a/servant/servant/AppCache.h +++ b/servant/servant/AppCache.h @@ -26,7 +26,7 @@ #include "util/tc_timeprovider.h" #include "util/tc_file.h" #include "util/tc_thread_mutex.h" -#include "servant/TarsLogger.h" +#include "servant/RemoteLogger.h" #define APPCACHE_ROOT_PATH "/cache" @@ -38,7 +38,7 @@ namespace tars /** * 缓存 */ -class AppCache : public TC_Singleton, public TC_ThreadMutex +class SVT_DLL_API AppCache : public TC_Singleton, public TC_ThreadMutex { public: AppCache() diff --git a/servant/servant/AppProtocol.h b/servant/servant/AppProtocol.h index c9a73ed196da803e4432c13343ab158475816a47..c48241ccf87d9dfb1ed1af7579bb839568c9aa0c 100644 --- a/servant/servant/AppProtocol.h +++ b/servant/servant/AppProtocol.h @@ -143,6 +143,8 @@ public: static vector http1Request(tars::RequestPacket& request, Transceiver *); static TC_NetWorkBuffer::PACKET_TYPE http1Response(TC_NetWorkBuffer &in, ResponsePacket& done); + // static vector httpJceRequest(taf::RequestPacket& request, Transceiver *); + // static TC_NetWorkBuffer::PACKET_TYPE httpJceResponse(TC_NetWorkBuffer &in, ResponsePacket& done); #if TARS_HTTP2 // ENCODE function, called by network thread diff --git a/servant/servant/Application.h b/servant/servant/Application.h index 00cf529b4b7770dfadb2486912155428542f8a56..7980ab3164be2d77e9314231fb30bb5d71adf0f6 100644 --- a/servant/servant/Application.h +++ b/servant/servant/Application.h @@ -30,9 +30,9 @@ #include "servant/ServantHandle.h" #include "servant/StatReport.h" #include "servant/CommunicatorFactory.h" -#include "servant/TarsLogger.h" -#include "servant/TarsConfig.h" -#include "servant/TarsNotify.h" +#include "servant/RemoteLogger.h" +#include "servant/RemoteConfig.h" +#include "servant/RemoteNotify.h" #if TARS_SSL #include "util/tc_openssl.h" @@ -40,7 +40,12 @@ namespace tars { -////////////////////////////////////////////////////////////////////// +//#ifndef GEN_PYTHON_MASK + +#define OUT_LINE (TC_Common::outfill("", '-', 80)) +#define OUT_LINE_LONG (TC_Common::outfill("", '=', 80)) +#define OUT_LINE_TAB(x) (TC_Common::outfill("", '-', 80 - 4*x)) + /** * 以下定义配置框架支持的命令 */ @@ -56,28 +61,29 @@ namespace tars #define TARS_CMD_SET_DAYLOG_LEVEL "tars.enabledaylog" //设置按天日志是否输出: tars.enabledaylog [remote|local]|[logname]|[true|false] #define TARS_CMD_CLOSE_CORE "tars.closecore" //设置服务的core limit: tars.setlimit [yes|no] #define TARS_CMD_RELOAD_LOCATOR "tars.reloadlocator" //重新加载locator的配置信息 - +#define TARS_CMD_RESOURCE "tars.resource" //get resource +#define TARS_CMD_VIEW_BID "tars.bid" //查看服务编译时间,build id ////////////////////////////////////////////////////////////////////// /** * 通知信息给notify服务, 展示在页面上 */ //上报普通信息 -#define TARS_NOTIFY_NORMAL(info) {TarsRemoteNotify::getInstance()->notify(NOTIFYNORMAL, info);} +#define TARS_NOTIFY_NORMAL(info) {RemoteNotify::getInstance()->notify(NOTIFYNORMAL, info);} //上报警告信息 -#define TARS_NOTIFY_WARN(info) {TarsRemoteNotify::getInstance()->notify(NOTIFYWARN, info);} +#define TARS_NOTIFY_WARN(info) {RemoteNotify::getInstance()->notify(NOTIFYWARN, info);} //上报错误信息 -#define TARS_NOTIFY_ERROR(info) {TarsRemoteNotify::getInstance()->notify(NOTIFYERROR, info);} +#define TARS_NOTIFY_ERROR(info) {RemoteNotify::getInstance()->notify(NOTIFYERROR, info);} //发送心跳给node 多个adapter分别上报 -#define TARS_KEEPALIVE(adapter) {TarsNodeFHelper::getInstance()->keepAlive(adapter);} +#define TARS_KEEPALIVE(adapter) {KeepAliveNodeFHelper::getInstance()->keepAlive(adapter);} //发送激活信息 -#define TARS_KEEPACTIVING {TarsNodeFHelper::getInstance()->keepActiving();} +#define TARS_KEEPACTIVING {KeepAliveNodeFHelper::getInstance()->keepActiving();} //发送TARS版本给node -#define TARS_REPORTVERSION(x) {TarsNodeFHelper::getInstance()->reportVersion(TARS_VERSION);} +#define TARS_REPORTVERSION(x) {KeepAliveNodeFHelper::getInstance()->reportVersion(TARS_VERSION);} ////////////////////////////////////////////////////////////////////// /** @@ -100,7 +106,7 @@ namespace tars /** * 服务基本信息 */ -struct ServerConfig +struct SVT_DLL_API ServerConfig { static std::string TarsPath; static std::string Application; //应用名称 @@ -127,12 +133,16 @@ struct ServerConfig static int NetThread; //servernet thread static bool ManualListen; //是否启用手工端口监听 static bool MergeNetImp; //网络线程和IMP线程合并(以网络线程个数为准) + static int BackPacketLimit; //回包积压检查 + static int BackPacketMin; //回包速度检查 #if TARS_SSL static std::string CA; static std::string Cert; static std::string Key; static bool VerifyClient; + static std::string Ciphers; #endif + static map Context; //框架内部用, 传递节点名称(以域名形式部署时) }; class PropertyReport; @@ -224,7 +234,6 @@ public: void addServant(const string &id) { ServantHelperManager::getInstance()->addServant(id, this, true); - } /** @@ -319,7 +328,17 @@ protected: * * @return bool */ - bool cmdViewVersion(const string& command, const string& params, string& result); + bool cmdViewVersion(const string &command, const string ¶ms, string &result); + + /** + * 查看服务的buildid(编译时间) + * @param command + * @param params + * @param result + * + * @return bool + */ + bool cmdViewBuildID(const string &command, const string ¶ms, string &result); /** * 使配置文件的property信息生效 @@ -369,6 +388,14 @@ protected: */ bool cmdReloadLocator(const string& command, const string& params, string& result); + /* + * view server resource + * @param command + * @param params + * @param result + */ + bool cmdViewResource(const string& command, const string& params, string& result); + protected: /** diff --git a/servant/servant/Communicator.h b/servant/servant/Communicator.h index 026f14841eb0c58bbff11c37926cafdfd50c22c7..3d232d6315327a4020eccfac10ddf5c88649fcca 100644 --- a/servant/servant/Communicator.h +++ b/servant/servant/Communicator.h @@ -26,8 +26,8 @@ #include "servant/ObjectProxyFactory.h" #include "servant/AsyncProcThread.h" #include "servant/CommunicatorEpoll.h" -#include "servant/TarsLogger.h" -#ifdef _USE_OPENTRACKING +#include "servant/RemoteLogger.h" +#ifdef TARS_OPENTRACKING #include "zipkin/opentracing.h" #include "zipkin/tracer.h" #include "zipkin/ip_address.h" @@ -77,10 +77,11 @@ struct ClientConfig /** * 通信器,用于创建和维护客户端proxy */ -class Communicator : public TC_HandleBase, public TC_ThreadRecMutex +class SVT_DLL_API Communicator : public TC_HandleBase, public TC_ThreadRecMutex { public: + typedef std::function custom_callback; /** * 构造函数 */ @@ -195,6 +196,11 @@ public: */ string getServantProperty(const string &sObj, const string& name); + /** + * 设置自动回调对象 + */ + void setServantCustomCallback(const string &sObj, custom_callback callback); + /** * 上报统计 * @return StatReport* @@ -218,12 +224,12 @@ public: */ vector getEndpoint(const string & objName); - /** - * 获取obj对应可用ip port列表 包括所有IDC的 - * @param sObjName - * @return vector - */ - vector getEndpoint4All(const string & objName); + /** + * 获取obj对应可用ip port列表 包括所有IDC的 + * @param sObjName + * @return vector + */ + vector getEndpoint4All(const string& objName); /** * 结束 @@ -240,6 +246,12 @@ public: */ int64_t getMinTimeout() { return _minTimeout; } + /** + * get resource info + * @return + */ + string getResourcesInfo(); + protected: /** * 初始化 @@ -370,6 +382,16 @@ protected: unordered_map> _objCtx; #endif + /** + * + */ + TC_SpinLock _callbackLock; + + /** + * callback + */ + unordered_map _callback; + /* * 异步线程数组 */ @@ -390,7 +412,7 @@ protected: */ size_t _asyncSeq = 0; -#ifdef _USE_OPENTRACKING +#ifdef TARS_OPENTRACKING public: struct TraceManager:public TC_HandleBase{ zipkin::ZipkinOtTracerOptions _zipkin_options; diff --git a/servant/servant/CommunicatorEpoll.h b/servant/servant/CommunicatorEpoll.h index d79d94cc7af3b24c65fbc2a40c6ca3da0ac8c048..12742b559f4c30294ecdd90fbeaed794ad70cc91 100644 --- a/servant/servant/CommunicatorEpoll.h +++ b/servant/servant/CommunicatorEpoll.h @@ -65,13 +65,9 @@ struct FDInfo } size_t iSeq; - - int fd; - - int iType; - + int fd; + int iType; void * p; - TC_Epoller::NotifyInfo notify; }; @@ -82,6 +78,7 @@ struct FDInfo class CommunicatorEpoll : public TC_Thread ,public TC_ThreadRecMutex { public: + /** * 构造函数 */ @@ -180,6 +177,18 @@ public: */ void pushAsyncThreadQueue(ReqMessage * msg); + /** + * set reconnect + * @param time + */ + void reConnect(int64_t ms, Transceiver*); + + /** + * communicator resource desc + * @return + */ + string getResourcesInfo(); + protected: /** * 处理函数 @@ -213,6 +222,11 @@ protected: */ void doStat(); + /** + * reconnect + */ + void reConnect(); + protected: /* * 通信器 @@ -261,6 +275,12 @@ protected: * 超时的检查时间间隔 */ int64_t _timeoutCheckInterval; + + /** + * auto reconnect Transceiver + */ + unordered_map _reconnect; + }; ///////////////////////////////////////////////////////////////////////////////////// diff --git a/servant/servant/Cookie.h b/servant/servant/Cookie.h new file mode 100644 index 0000000000000000000000000000000000000000..bb2d3dc6b433570c47cae741aeb3a951b35f990e --- /dev/null +++ b/servant/servant/Cookie.h @@ -0,0 +1,72 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT 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 __TARS_COOKIE_H__ +#define __TARS_COOKIE_H__ + + +/** + * cookie操作类 + */ +class CookieOp +{ +public: + /** + * 构造函数 + */ + CookieOp() + { + } + + /** + * 析构函数,清理掉已设置的cookie + */ + ~CookieOp() + { + ServantProxyThreadData * td = ServantProxyThreadData::getData(); + assert(NULL != td); + if (td) + { + td->_cookie.clear(); + } + } + + /** + * 获取cookie + */ + static map & getCookie() + { + ServantProxyThreadData * td = ServantProxyThreadData::getData(); + assert(NULL != td); + + return td->_cookie; + } + + /** + * 设置cookie + */ + void setCookie(const map &cookie) + { + ServantProxyThreadData * td = ServantProxyThreadData::getData(); + assert(NULL != td); + if(td) + { + td->_cookie = cookie; + } + } +}; + +#endif \ No newline at end of file diff --git a/servant/servant/TarsCurrent.h b/servant/servant/Current.h similarity index 92% rename from servant/servant/TarsCurrent.h rename to servant/servant/Current.h index b59e20e245f2996d1180df2f6810dfdf569ac6a7..74476cff0805c3ecb46bcd9b224239dc9ad2d821 100644 --- a/servant/servant/TarsCurrent.h +++ b/servant/servant/Current.h @@ -31,7 +31,7 @@ class ServantHandle; /** * 当前请求的上下文 */ -class TarsCurrent : public TC_HandleBase +class Current : public TC_HandleBase { public: typedef std::map TARS_STATUS; @@ -42,12 +42,12 @@ public: * 构造函数 * @param pServantHandle */ - TarsCurrent(ServantHandle *pServantHandle); + Current(ServantHandle *pServantHandle); /** * 析构 */ - ~TarsCurrent(); + ~Current(); /** * 获取IP @@ -56,6 +56,12 @@ public: const string &getIp() const; /** + * get host name + * @return + */ + const string &getHostName() const; + + /** * 获取端口 * @return int */ @@ -223,6 +229,22 @@ public: */ void sendResponse(const char* buff, uint32_t len); + /** + * 设置cookie + */ + void setCookie(const map &cookie) + { + _cookie = cookie; + } + + /** + * 获取cookie + */ + map & getCookie() + { + return _cookie; + } + protected: friend class ServantHandle; @@ -297,6 +319,11 @@ protected: * 设置额外返回的内容 */ map _responseContext; + + /** + * cookie + */ + map _cookie; }; ////////////////////////////////////////////////////////////// } diff --git a/servant/servant/EndpointInfo.h b/servant/servant/EndpointInfo.h index e03380a83a4525cbc9751b174aba5c8de1821d84..964956774e70aa9c41c53f3b6b2c157c9c199071 100755 --- a/servant/servant/EndpointInfo.h +++ b/servant/servant/EndpointInfo.h @@ -54,11 +54,16 @@ public: EndpointInfo(const string& host, uint16_t port, TC_Endpoint::EType type, int32_t grid, const string & setDivision, int qos, int weight = -1, unsigned int weighttype = 0, int authType = 0); /** - * 地址的字符串描述,不带set信息 - * - * @return string + * get endpoint + * @return */ - const string& descNoSetInfo() const; + const TC_Endpoint &getEndpoint() const { return _ep; } +// /** +// * 地址的字符串描述,不带set信息 +// * +// * @return string +// */ +// const string& descNoSetInfo() const; /** * 地址的字符串描述 @@ -70,15 +75,15 @@ public: return _desc; } - /** - * 比较的地址的字符串描述 - * - * @return string - */ - const string & compareDesc() const - { - return _cmpDesc; - } +// /** +// * 比较的地址的字符串描述 +// * +// * @return string +// */ +// const string & compareDesc() const +// { +// return _cmpDesc; +// } /** * 详细地址字符串描述 @@ -181,13 +186,13 @@ public: */ bool operator == (const EndpointInfo& r) const; - /** - *等于,set信息不参与比较 - *@param r - * - *@return bool - */ - bool equalNoSetInfo(const EndpointInfo& r) const; +// /** +// *等于,set信息不参与比较 +// *@param r +// * +// *@return bool +// */ +// bool equalNoSetInfo(const EndpointInfo& r) const; /** * 小于 diff --git a/servant/servant/EndpointManager.h b/servant/servant/EndpointManager.h index f4ff3973b7e7677a0d870dc9e11a32df37c94b41..0ce8e9fa9cebba1621aac8b72e45bc5c4bb05751 100644 --- a/servant/servant/EndpointManager.h +++ b/servant/servant/EndpointManager.h @@ -33,8 +33,8 @@ namespace tars enum GetEndpointType { E_DEFAULT = 0, - E_ALL = 1, - E_SET = 2, + E_ALL = 1, + E_SET = 2, E_STATION = 3 }; @@ -129,9 +129,9 @@ public: */ virtual void doNotify() = 0; - /* - * 设置主控的代理 - */ + /* + * 设置主控的代理 + */ int setLocatorPrx(QueryFPrx prx); /* @@ -168,7 +168,7 @@ private: /* * 主控的请求的响应到了,做相应的处理 */ - void doEndpoints(const vector& activeEp, const vector& inactiveEp, int iRet, bool bSync = false); + void doEndpoints(const vector& activeEp, const vector& inactiveEp, int iRet, bool bSync = false); /* * 请求主控异常,做相应的处理 @@ -246,7 +246,11 @@ protected: */ set _inactiveEndpoints; - + /** + * 是否是root servant + */ + bool _rootServant; + private: /////////以下是请求主控的策略信息///////////////// @@ -335,7 +339,14 @@ public: */ void notifyEndpoints(const set & active, const set & inactive, bool bSync = false); - /* + /** + * 更新 + * @param active + * @param inactive + */ + void updateEndpoints(const set & active, const set & inactive); + + /* * 重写基类的实现 */ void doNotify(); diff --git a/servant/servant/Global.h b/servant/servant/Global.h index 89073b2516e17e891a16e89c643257494e73f829..30a7e13cd46947b48b53c88ae286804a359d66d4 100755 --- a/servant/servant/Global.h +++ b/servant/servant/Global.h @@ -50,7 +50,7 @@ class AdapterProxy; class ServantProxy; class ServantProxyCallback; class ObjectProxy; -class TarsCurrent; +class Current; class FDReactor; class Transceiver; class StatFProxy; @@ -58,19 +58,27 @@ class StatReport; class ServantProxyFactory; class ObjectProxyFactory; class AsyncProcThread; +class LocalRollLogger; +class RemoteConfig; +class RemoteTimeLogger; +class RemoteNotify; typedef TC_AutoPtr CommunicatorPtr; typedef TC_AutoPtr ServantPrx; typedef TC_AutoPtr ServantProxyCallbackPtr; typedef TC_AutoPtr ObjectPrx; -typedef TC_AutoPtr TarsCurrentPtr; +typedef TC_AutoPtr CurrentPtr; typedef TC_AutoPtr StatFPrx; typedef TC_AutoPtr StatReportPtr; typedef TC_AutoPtr FDReactorPtr; -// typedef TC_AutoPtr ServantProxyFactoryPtr; -//typedef TC_AutoPtr ObjectProxyFactoryPtr; typedef TC_AutoPtr AsyncProcThreadPtr; +typedef CurrentPtr TarsCurrentPtr; +typedef RemoteConfig TarsRemoteConfig; +typedef RemoteNotify TarsRemoteNotify; +typedef LocalRollLogger TarsRollLogger; +typedef RemoteTimeLogger TarsTimeLogger; + ////////////////////////////////////////////////////////////// /** * 定义TARS网络调用的异常基类 diff --git a/servant/servant/TarsNodeF.h b/servant/servant/KeepAliveNodeF.h similarity index 94% rename from servant/servant/TarsNodeF.h rename to servant/servant/KeepAliveNodeF.h index 7dde222959f75304a6104020977d282426d4470d..756189a9384537c64c6553e93a6481e7033b3ff5 100644 --- a/servant/servant/TarsNodeF.h +++ b/servant/servant/KeepAliveNodeF.h @@ -28,7 +28,7 @@ namespace tars * 给node发送心跳 * 调用keepAlive异步发送心跳给node */ -class TarsNodeFHelper : public TC_Singleton,public TC_ThreadMutex +class KeepAliveNodeFHelper : public TC_Singleton,public TC_ThreadMutex { public: diff --git a/servant/servant/Message.h b/servant/servant/Message.h index 8760e39b644732db6a688fe06a4765d53d3b0813..ee922c8bf70776c6902ff43fee4019d3e0a035f1 100644 --- a/servant/servant/Message.h +++ b/servant/servant/Message.h @@ -49,8 +49,8 @@ struct CheckTimeoutInfo , frequenceFailInvoke(5) , minFrequenceFailTime(5) , radio(0.5) - , tryTimeInterval(30) - , maxConnectExc(5) + , tryTimeInterval(10) + , maxConnectExc(1) { } @@ -90,61 +90,6 @@ struct CheckTimeoutInfo uint32_t maxConnectExc; }; -///////////////////////////////////////////////////////////////////////// -/* - * stat采样信息(用于调用链时序分析) - */ -struct SampleKey -{ - /* - * 构造函数 - */ - SampleKey() - : _root(true) - , _unid("") - , _depth(0) - , _width(0) - , _parentWidth(0) - {} - - /* - * 初始化 - */ - void init() - { - _root = true; - _unid.clear(); - _depth = 0; - _width = 0; - _parentWidth = 0; - } - - /* - * 是否根节点 在根节点产生唯一id - */ - bool _root; - - /* - * 唯一id - */ - string _unid; - - /* - * 深度 - */ - int _depth; - - /* - * 广度 - */ - int _width; - - /* - * 父节点广度值 - */ - int _parentWidth; -}; - ///////////////////////////////////////////////////////////////////////// /** * 用于同步调用时的条件变量 @@ -211,6 +156,11 @@ struct ReqMessage : public TC_HandleBase */ ~ReqMessage() { + if(deconstructor) + { + deconstructor(); + } + if(pMonitor != NULL) { delete pMonitor; @@ -263,6 +213,7 @@ struct ReqMessage : public TC_HandleBase ObjectProxy * pObjectProxy; //调用端的proxy对象 RequestPacket request; //请求消息体 + std::function deconstructor; //析构时调用 shared_ptr response; //响应消息体 // string sReqData; //请求消息体 shared_ptr sReqData; //请求消息体 @@ -289,15 +240,16 @@ struct ReqMessage : public TC_HandleBase uint32_t iCoroId; //协程的id -#ifdef _USE_OPENTRACKING +#ifdef TARS_OPENTRACKING std::unordered_map trackInfoMap; //调用链信息 #endif + + map cookie; // cookie内容 }; typedef TC_AutoPtr ReqMessagePtr; typedef TC_LoopQueue ReqInfoQueue; -#define HTTP2 "http2" } diff --git a/servant/servant/NotifyObserver.h b/servant/servant/NotifyObserver.h index ab91723607ab6c06438e1818271995419a3fe840..2d3ca15d534f9be742f7bbd30f1c2af86a2ea704 100644 --- a/servant/servant/NotifyObserver.h +++ b/servant/servant/NotifyObserver.h @@ -18,7 +18,7 @@ #define __TARS_NOTIFY_OBSERVER_H_ #include "servant/Global.h" -#include "servant/TarsCurrent.h" +#include "servant/Current.h" #include "util/tc_singleton.h" namespace tars diff --git a/servant/servant/ObjectProxy.h b/servant/servant/ObjectProxy.h index 5aa7738cae912517ead5c53c4d5a9a5bb501a1d6..d797375c47b15e066d22994d7ddc700cc4e0e640 100644 --- a/servant/servant/ObjectProxy.h +++ b/servant/servant/ObjectProxy.h @@ -87,6 +87,19 @@ public: */ void doInvoke(); + /** + * + * @param adapterProxy + */ +// void doInvoke(AdapterProxy *adapterProxy); + + /** + * + * @param active + * @param inactive + */ + void onNotifyEndpoints(const set & active,const set & inactive); + /** * 设置协议解析器 * @return UserProtocol& @@ -121,10 +134,13 @@ public: ServantProxyCallbackPtr getPushCallback(); /** - * 获取所有的adapter + * connected */ - // const vector & getAdapters() const; + void onConnect(AdapterProxy *adapterProxy); + /** + * 获取所有的adapter + */ void mergeStat(map & mStatMicMsg); /** @@ -132,14 +148,6 @@ public: */ void doTimeout(); - /** - * Obj的超时队列的长度 - */ - size_t timeoutQSize() - { - return _reqTimeoutQueue.size(); - } - /** * 获取CommunicatorEpoll* */ @@ -157,7 +165,43 @@ public: return _name; } + /** + * address + * @return + */ + inline const string &hash() const + { + return _hash; + } + + /** + * address + * @return + */ + inline const string &address() const + { + return _address; + } + /** + * reconnect + * @param second + */ + inline void reconnect(int second) + { + _reConnectSecond = second; + } + + /** + * reconnect + * @param second + */ + inline int reconnect() + { + return _reConnectSecond; + } + + /** * 判断此obj是否走按set规则调用流程,如果是直连方式,即使服务端是启用set的,也不认为是按set规则调用的 */ bool isInvokeBySet() const @@ -215,12 +259,34 @@ public: _servantProxy = pServantProxy; } -protected: + /** + * + * @return + */ + inline EndpointManager* getEndpointManager() + { + return _endpointManger.get(); + } /** - * 处理请求异常 + * get all adapter proxy + * @return */ - void doInvokeException(ReqMessage * msg); + const vector & getAdapters(); + + /** + * + * @param ep + */ + void onSetInactive(const EndpointInfo& ep); + +protected: + + /** + * 处理请求异常 + * + */ + void doInvokeException(ReqMessage * msg); private: /* @@ -229,10 +295,22 @@ private: CommunicatorEpoll * _communicatorEpoll; /* - * object的名称 + * [obname]#hash@tcp -h xxxx -p xxx */ string _name; + /** + * obname#[hash]@tcp -h xxxx -p xxx + * ever hash has one connection + */ + string _hash; + + /** + * obname#hash@[tcp -h xxxx -p xxx] + * ever hash has one connection + */ + string _address; + /* * 按set规则调用的set名称 */ @@ -244,7 +322,7 @@ private: bool _isInvokeBySet; /* - * 是否调用了tars_set_protocol设置过proxy的协议函数, + * 是否调用了taf_set_protocol设置过proxy的协议函数, * 设置过了就不在设置 */ bool _hasSetProtocol; @@ -259,6 +337,11 @@ private: */ int _conTimeout; + /** + * reconnect, 0: not reconnect + */ + int _reConnectSecond = 0; + /* * 超时控制策略信息 */ diff --git a/servant/servant/PropertyReport.h b/servant/servant/PropertyReport.h index 6705ebdb5e5e08b63694ccf09ad9f90322cef79f..6674c70afc6c03a0aab29e212e3a0210d8e8e7e0 100755 --- a/servant/servant/PropertyReport.h +++ b/servant/servant/PropertyReport.h @@ -19,7 +19,7 @@ #include "util/tc_lock.h" #include "util/tc_autoptr.h" -//#include "util/tc_thread_mutex.h" +#include "util/tc_thread_mutex.h" #include "util/tc_spin_lock.h" #include #include @@ -80,7 +80,7 @@ public: string get(); void set(int o) { _sum += o;++_count; } protected: - void clear() { _sum = 0; _count = 0; } + void clear() { _sum = 0; _count = 0; } private: int _sum; int _count; @@ -170,7 +170,7 @@ typedef TC_AutoPtr PropertyReportPtr; */ template -class PropertyReportImp : public PropertyReport, public TC_SpinLock +class PropertyReportImp : public PropertyReport, public TC_ThreadMutex { public: using PropertyReportData = std::tuple; @@ -195,7 +195,7 @@ public: */ void report(int iValue) override { - TC_LockT lock(*this); + TC_LockT lock(*this); Helper::value>::Report(*this, iValue); } @@ -207,7 +207,7 @@ public: */ vector > get() override { - TC_LockT lock(*this); + TC_LockT lock(*this); return Helper::value>::Get(*this); } diff --git a/servant/servant/TarsConfig.h b/servant/servant/RemoteConfig.h similarity index 97% rename from servant/servant/TarsConfig.h rename to servant/servant/RemoteConfig.h index d52f8c877a00501ccd245c080b674c072ae2f77f..73129bcebd01f8223e54b2e006181102fb9e840b 100644 --- a/servant/servant/TarsConfig.h +++ b/servant/servant/RemoteConfig.h @@ -43,7 +43,7 @@ namespace tars * */ -class TarsRemoteConfig : public TC_Singleton +class RemoteConfig : public TC_Singleton { public: /** @@ -57,7 +57,7 @@ public: * * @return int */ - int setConfigInfo(const CommunicatorPtr &comm, const string &obj, const string & app, const string &serverName, const string& basePath,const string& setdivision="",int maxBakNum=5); + int setConfigInfo(const CommunicatorPtr &comm, const string &obj, const string & app, const string &serverName, const string& basePath,const string& setdivision="",int maxBakNum = 5); /** * 读取ConfigServer上配置文件到本地,并备份原文件 diff --git a/servant/servant/RemoteLogger.h b/servant/servant/RemoteLogger.h new file mode 100755 index 0000000000000000000000000000000000000000..0d1dbe74b8fe2b59194944b32525e4133becd88a --- /dev/null +++ b/servant/servant/RemoteLogger.h @@ -0,0 +1,901 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT 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 __TARS_LOGGER_H__ +#define __TARS_LOGGER_H__ + +#include "util/tc_logger.h" +#include "util/tc_file.h" +#include "util/tc_singleton.h" +#include "servant/Global.h" +#include "servant/LogF.h" +#include "servant/PropertyReport.h" + +#define DYEING_DIR "tars_dyeing" +#define DYEING_FILE "dyeing" + +namespace tars +{ + +/** + * LOG的库说明: + * 1 循环日志采用TLOGERROR(...),TLOGDEBUG(...) + * 2 循环日志不上传到服务器 + * 3 按天日志采用DLOG, FDLOG来记录 + * 4 按天日志也可以不上传到远程服务器:DLOG("")->disableRemote(); + * 5 按天日志可以改变每天一个文件的方式: + * DLOG("abc3")->setFormat("%Y%m%d%H"); + * 每个小时一个文件 + */ + +/***************************************************************************** +实现方式说明(只介绍按时间的日志, 会写到tarslog): + 1 自定义时间日志的WriteT类:RemoteTimeWriteT + 2 在RemoteTimeWriteT类中, 写入到远程 + 3 定义远程日志类:typedef TC_Logger RemoteTimeLogger; + 4 为了保证远程的写日志也是在单独线程处理,重新定义本地按天日志类 + 5 自定义时间日志的WriteT类:TimeWriteT + 6 在TimeWriteT类中包含RemoteTimeLogger对象 + 7 在TimeWriteT类的写入操作中, 写入本地文件后, 同时写入到RemoteTimeLogger对象中 + 8 RemoteTimeLogger会在RemoteTimeWriteT对象中, 异步写入到远程 + 9 从而本地文件写和远程写不在一个线程中. +*****************************************************************************/ + +/////////////////////////////////////////////////////////////////////////////// + +class RollWriteT +{ +public: + RollWriteT(); + ~RollWriteT(); + + void operator()(ostream &of, const deque > &ds); + + void setDyeingLogInfo(const string &sApp, const string &sServer, const string & sLogPath, + int iMaxSize, int iMaxNum, const CommunicatorPtr &comm, const string & sLogObj); + +protected: + + TC_RollLogger *_dyeingRollLogger; + + static int _dyeingThread; + + string _app; + string _server; + string _logPath; + int _maxSize; + int _maxNum; + + /** + * 染色远程滚动日志代理 + */ + LogPrx _logPrx; + + +}; + + +/** + * 本地日志帮助类, 单件 + * 循环日志单件是永生不死的, 保证任何地方都可以使用 + * 当该对象析够以后, 则直接cout出来 + */ +class LocalRollLogger : public TC_Singleton +{ +public: + enum + { + NONE_LOG = 1, /**所有的log都不写*/ + ERROR_LOG = 2, /**写错误log*/ + WARN_LOG = 3, /**写错误,警告log*/ + DEBUG_LOG = 4, /**写错误,警告,调试log*/ + INFO_LOG = 5, /**写错误,警告,调试,Info log*/ + TARS_LOG = 6 /**写错误,警告,调试,Info log*/ + }; +public: + typedef TC_Logger RollLogger; + + /** + * 设置本地信息 + * @param app, 业务名称 + * @param server, 服务名称 + * @param logpath, 日志路径 + * @param iMaxSize, 文件最大大小,字节 + * @param iMaxNum, 文件最大数 + */ + void setLogInfo(const string &sApp, const string &sServer, const string &sLogpath, int iMaxSize = 1024*1024*50, int iMaxNum = 10, const CommunicatorPtr &comm=NULL, const string &sLogObj=""); + + /** + * 设置同步写日志 + * + * @param bSync + */ + void sync(bool bSync = true); + + /** + * 获取循环日志 + * + * @return RollLogger + */ + RollLogger *logger() { return &_logger; } + + /** + * 染色日志是否启用 + * @param bEnable + */ + void enableDyeing(bool bEnable, const string& sDyeingKey = ""); + +protected: + + /** + * 应用 + */ + string _app; + + /** + * 服务名称 + */ + string _server; + + /** + * 日志路径 + */ + string _logpath; + + /** + * 循环日志 + */ + RollLogger _logger; + + /** + * 本地线程组 + */ + TC_LoggerThreadGroup _local; + +}; + +/////////////////////////////////////////////////////////////////////////////////////// +// +/** + * 写日志线程 + * 将写本地日志和远程分开到不同的线程 + * 作为单件存在, 且是永生不死的单件 + */ +class TarsLoggerThread : public TC_Singleton +{ +public: + /** + * 构造函数 + */ + TarsLoggerThread(); + + /** + * 析够函数 + */ + ~TarsLoggerThread(); + + /** + * 本地写日志线程 + */ + TC_LoggerThreadGroup* local(); + + /** + * 远程写日志线程 + * + * @return TC_LoggerThreadGroup* + */ + TC_LoggerThreadGroup* remote(); + +protected: + + /** + * 本地线程组 + */ + TC_LoggerThreadGroup _local; + + /** + * 远程写线程组 + */ + TC_LoggerThreadGroup _remote; +}; + +/////////////////////////////////////////////////////////////////////////////////////// +class TimeWriteT; + +/** + * 远程的Log写操作类 + */ +class RemoteTimeWriteT +{ +public: + RemoteTimeWriteT(); + ~RemoteTimeWriteT(); + + /** + * 构造函数 + */ + void setTimeWriteT(TimeWriteT *pTimeWrite); + + /** + * 具体调用 + * @param of + * @param buffer + */ + void operator()(ostream &of, const deque > &buffer); + +protected: + /** + * 同步到远程 + */ + void sync2remote(const vector &buffer); + + /** + * 染色日志同步到远程 + */ + void sync2remoteDyeing(const vector &buffer); + +protected: + /** + * 指针 + */ + TimeWriteT *_timeWrite; + +}; + +//////////////////////////////////////////////////////////////////////////// +/** + * 写Logger + */ +class TimeWriteT +{ +public: + typedef TC_Logger RemoteTimeLogger; + + typedef TC_Logger DyeingTimeLogger; + + /** + * 构造 + */ + TimeWriteT(); + + /** + * 析够 + */ + ~TimeWriteT(); + + /** + * 设置基本信息 + * @param app, 应用名称 + * @param server, 服务名称 + * @param file, 日志文件名 + * @param sFormat, 格式 + * @param setdivision,set名称 + * @param sLogType,日志记录类型 + */ + void setLogInfo(const LogPrx &logPrx, const string &sApp, const string &sServer, const string &sFile, const string &sLogpath, const string &sFormat, const string& setdivision = "", const string& sLogType = "", const PropertyReportPtr &reportSuccPtr = NULL, const PropertyReportPtr &reportFailPtr = NULL); + + /** + * 设置代理 + * @param logPrx 代理信息 + */ + void setLogPrx(const LogPrx &logPrx); + + /** + * 远程日志功能打开或关闭 + * @param bEnable + */ + void enableRemote(bool bEnable) { _remote = bEnable; } + + /** + * 本地日志功能功能打开或关闭 + * @param bEnable + */ + void enableLocal(bool bEnable); + + /** + * 染色日志功能打开或关闭 + * @param bEnable + */ + void enableDyeing (bool bEnable, const string& sDyeingKey = ""); + + + /** + * @brief 日志文件名是否带.log后缀 + * @param bEnable + */ + void enableSufix(bool bEnable=true){_hasSufix = bEnable;} + /** + * @brief 是否允许框架在日志文件名上增加业务相关的标识 + * @param bEnable + */ + void enablePrefix(bool bEnable=true){_hasAppNamePrefix = bEnable;} + /** + * @brief 日志文件名中用户自定义字符与日期字符间的连接符,默认是"_" + * @param str + */ + void setFileNameConcatStr(const string& str) {_concatStr = str;} + + /** + * @brief 框架中增加的日志内容之间的分割符,默认是"|" + * @param str + */ + void setSeparator(const string& str) {_separ = str;} + + /** + * @brief 框架中日期和时间之间是否需要加中括号[],有些统计由特殊需求;默认不加 + * @param bEnable + */ + void enableSqareWrapper(bool bEnable) {_hasSquareBracket = bEnable;} + + + /** + * 设置时间格式("%Y%m%d") + * @param sFormat + */ + void setFormat(const string &sFormat) { _format = sFormat;} + + /** + * 具体调用 + * @param of + * @param buffer + */ + void operator()(ostream &of, const deque > &buffer); + +protected: + + /** + * 友元 + */ + friend class RemoteTimeWriteT; + + /** + * 记录错误文件 + * @param buffer + */ + void writeError(const vector &buffer); + + /** + * 记录错误文件 + * @param buffer + */ + void writeError(const deque > &buffer); + + /** + * 初始化logger + */ + void initError(); + + /** + * 初始化染色日志 + */ + void initDyeingLog(); + +protected: + + /** + * 远程时间日志 + */ + RemoteTimeLogger *_remoteTimeLogger; + + /** + * 本地功能 + */ + bool _local; + + /** + * 远程功能 + */ + bool _remote; + + /** + * 远程服务句柄 + */ + LogPrx _logPrx; + + /** + * app名称 + */ + string _app; + + /** + * 服务名称 + */ + string _server; + + /** + * 日志文件名称 + */ + string _file; + + /** + * 时间格式 + */ + string _format; + + /** + * 具体文件 + */ + string _filePath; + + /** + * 错误文件 + */ + TC_DayLogger _logger; + + /** + * 缺省写模式 + */ + TC_DefaultWriteT _wt; + + /** + * 染色日志 + */ + static int _dyeing; + + /** + * 染色日志目录路径 + */ + string _dyeingFilePath; + + /** + * 远程时间日志 + */ + DyeingTimeLogger *_dyeingTimeLogger; + + /** + * set分组信息 + */ + string _setDivision; + + /** + * 日志文件名是否带.log后缀 + */ + bool _hasSufix; + /** + * 是否允许框架在日志文件名上增加业务相关的标识 + */ + bool _hasAppNamePrefix; + + /** + * 日志文件名中用户自定义字符与日期字符间的连接符,默认是"_" + */ + string _concatStr; + /** + * 分隔符 + */ + string _separ; + /** + * 日期部分是否加上[] + */ + bool _hasSquareBracket; + + /* + * 本地日志的记录类型,格式为LogType.toString()返回值,如果不采用LogType,则该值为"" + */ + string _logType; + + /* + * 对于远程日志,上报同步到logser的成功量,默认不上报 + */ + PropertyReportPtr _reportSuccPtr; + + /* + * 对于远程日志,上报同步到logser的失败量,默认不上报 + */ + PropertyReportPtr _reportFailPtr; +}; + +//////////////////////////////////////////////////////////////////////////// +/** + * 远程日志帮助类, 单件 + */ +class RemoteTimeLogger : public TC_HandleBase + , public TC_ThreadLock + , public TC_Singleton +{ +public: + + //定义按时间滚动的日志 + typedef TC_Logger TimeLogger; + + /** + * 构造 + */ + RemoteTimeLogger(); + + /** + * 析够 + */ + ~RemoteTimeLogger(); + + /** + * 设置本地信息 + * @param comm, 通信器 + * @param obj, 日志对象名称 + * @param app, 业务名称 + * @param server, 服务名称 + * @param logpath, 日志路径 + */ + void setLogInfo(const CommunicatorPtr &comm, const string &obj, const string &sApp, const string &sServer, const string &sLogpath,const string& setdivision="", const bool &bLogStatReport=false); + + /** + * 初始化设置时间格式("%Y%m%d") + * 不要动态修改, 线程不安全 + * 如果有需要, 初始化后直接修改 + * @param sFormat, 文件名称, 为空表示缺省的时间日志 + */ + void initFormat(const string &sFile, const string &sFormat,const LogTypePtr& logTypePtr=NULL); + void initFormat(const string &sApp, const string &sServer,const string &sFile, const string &sFormat,const LogTypePtr& logTypePtr=NULL); + /** + * 初始化设置时间格式("%Y%m%d") + * 不要动态修改, 线程不安全 + * 如果有需要, 初始化后直接修改 + * @param sFormat, 文件名称, 为空表示缺省的时间日志 + * @param frequency 支持每多少天/小时/分钟,详见TC_logger.h中关于TarsLogByDay,TarsLogByHour,TarsLogByMinute的描述 + * + * 用法: 按两个小时记录日志 + * initFormat("logfile",TarsLogByHour::FORMAT,2); + */ + template + void initFormatWithType(const string &sFile, const string &sFormat,size_t frequency) + { + LogTypePtr logTypePtr = new TLogType(sFormat,frequency); + initFormat(sFile,sFormat,logTypePtr); + } + + template + void initFormatWithType(const string &sApp, const string &sServer,const string &sFile, const string &sFormat,size_t frequency) + { + LogTypePtr logTypePtr = new TLogType(sFormat,frequency); + initFormat(sApp,sServer,sFile,sFormat,logTypePtr); + } + /** + * 获取时间日志 + * @param file + */ + TimeLogger *logger(const string &sFile = ""); + + /** + * 获取时间日志 + * @param app, 业务名称 + * @param server, 服务名称 + * @param file + */ + TimeLogger *logger(const string &sApp, const string &sServer,const string &sFile = ""); + + /** + * 同步写本地时间日志(远程日志一定是异步写的, 无法调整) + * @param bSync + */ + void sync(const string &sFile, bool bSync); + + /** + * 远程时间日志 + * @param sFile, 文件名称, 为空表示缺省的时间日志 + * @param bEnable + */ + void enableRemote(const string &sFile, bool bEnable); + + /** + * 远程时间日志 + * @param sApp,应用名称 + * @param sServer,服务名称 + * @param sFile, 文件名称, 为空表示缺省的时间日志 + * @param bEnable + */ + void enableRemoteEx(const string &sApp, const string &sServer,const string &sFile, bool bEnable); + /** + * 本地时间日志 + * @param sFile,文件名称, 为空表示缺省的时间日志 + * @param bEnable + */ + void enableLocal(const string &sFile, bool bEnable); + /** + * 本地时间日志 + * @param sApp,应用名称 + * @param sServer,服务名称 + * @param sFile, 文件名称, 为空表示缺省的时间日志 + * @param bEnable + */ + void enableLocalEx(const string &sApp, const string &sServer,const string &sFile, bool bEnable); + + /** + * @brief 日志文件名是否带.log后缀,影响全部日志文件 + * @param bEnable + */ + void enableSufix(bool bEnable=true){_hasSufix = bEnable;} + /** + * @brief 是否允许框架在日志文件名上增加业务相关的标识,影响全部日志文件 + * @param bEnable + */ + void enablePrefix(bool bEnable=true){_hasAppNamePrefix = bEnable;} + /** + * @brief 日志文件名中用户自定义字符与日期字符间的连接符,默认是"_",影响全部日志文件 + * @param str + */ + void setFileNameConcatStr(const string& str) {_concatStr = str;} + + /** + * @brief 框架中增加的日志内容之间的分割符,默认是"|",影响全部日志文件 + * @param str + */ + void setSeparator(const string& str) {_separ = str;} + + /** + * @brief 框架中日期和时间之间是否需要加中括号[],有些统计由特殊需求;默认不加,影响全部日志文件 + * @param bEnable + */ + void enableSqareWrapper(bool bEnable) {_hasSquareBracket = bEnable;} + /** + * @brief 是否输出本地日志文件,影响全部日志文件 + * @param bEnable + */ + void enableLocalLog(bool bEnable) {_local = bEnable;} + /** + * @brief 是否输出远程日志文件,影响全部日志文件 + * @param bEnable + */ + void enableRemoteLog(bool bEnable) {_remote = bEnable;} +protected: + + /** + * 初始化时间日志 + * @param pTimeLogger + * @param sFile + * @param sFormat + * @param frequence, 每多少天/小时/分钟,单位是秒 + */ + void initTimeLogger(TimeLogger *pTimeLogger, const string &sFile, const string &sFormat,const LogTypePtr& logTypePtr=NULL); + + /** + * 初始化时间日志 + * @param pTimeLogger + * @param sApp + * @param sServer + * @param sFile + * @param sFormat + * @param frequence, 每多少天/小时/分钟,单位是秒 + */ + + void initTimeLogger(TimeLogger *pTimeLogger,const string &sApp, const string &sServer, const string &sFile, const string &sFormat,const LogTypePtr& logTypePtr=NULL); + +protected: + + /** + * 通信器 + */ + CommunicatorPtr _comm; + + /** + * 远程服务句柄 + */ + LogPrx _logPrx; + + /** + * 应用 + */ + string _app; + + /** + * 服务名称 + */ + string _server; + + /** + * 日志路径 + */ + string _logpath; + + /** + * 缺省按天日志 + */ + TimeLogger *_defaultLogger; + + /** + * 远程日志 + */ + map _loggers; + /** + * set分组信息 + */ + string _setDivision; + + /** + * 是否带.log后缀 + */ + bool _hasSufix; + /** + * 是否允许框架在日志文件名上增加业务相关的标识 + */ + bool _hasAppNamePrefix; + + /** + * 日志文件名中用户自定义字符与日期字符间的连接符,默认是"_" + */ + string _concatStr; + /** + * 分隔符 + */ + string _separ; + /** + * 日期部分是否加上[] + */ + bool _hasSquareBracket; + /** + * 是否输出本地日志 + */ + bool _local; + /** + * 是否输出远程日志 + */ + bool _remote; + + /* + * 服务日志上报logser是否上报成功数量 + */ + bool _logStatReport; +}; + +/** + * 染色开关类,析构时关闭 + */ +class TarsDyeingSwitch +{ +public: + /** + * 构造函数,默认不打开染色日志 + */ + TarsDyeingSwitch() + :_needDyeing(false) + { + } + + /** + * 析构函数,关闭已打开的染色日志 + */ + ~TarsDyeingSwitch() + { + if(_needDyeing) + { + LocalRollLogger::getInstance()->enableDyeing(false); + + ServantProxyThreadData * td = ServantProxyThreadData::getData(); + assert(NULL != td); + if (td) + { + td->_dyeing = false; + td->_dyeingKey = ""; + } + } + } + + /** + * 获取染色的key + * + * @param key + * @return bool + */ + static bool getDyeingKey(string & sDyeingkey) + { + ServantProxyThreadData * td = ServantProxyThreadData::getData(); + assert(NULL != td); + + if (td && td->_dyeing == true) + { + sDyeingkey = td->_dyeingKey; + return true; + } + return false; + } + + /** + * 启用染色日志 + */ + void enableDyeing(const string & sDyeingKey = "") + { + LocalRollLogger::getInstance()->enableDyeing(true); + + ServantProxyThreadData * td = ServantProxyThreadData::getData(); + assert(NULL != td); + if(td) + + { + td->_dyeing = true; + td->_dyeingKey = sDyeingKey; + } + _needDyeing = true; + _dyeingKey = sDyeingKey; + } + +protected: + bool _needDyeing; + string _dyeingKey; +}; + + +#if TARGET_PLATFORM_WINDOWS +#define _filename(x) (strrchr(x,'\\')?strrchr(x,'\\')+1:x) +#define FILE_FUNC_LINE " [" << _filename(__FILE__) << "::" << __FUNCTION__ << "::" << __LINE__ << "] " +#else +#define FILE_FUNC_LINE " [" << __FILE__ << "::" << __FUNCTION__ << "::" << __LINE__ << "] " +#endif + +/** + * 循环日志 + */ +#define LOG (LocalRollLogger::getInstance()->logger()) + +/** + * @brief 按级别循环日志宏 + * + * @param level 日志等级,LocalRollLogger::INFO_LOG,LocalRollLogger::DEBUG_LOG,LocalRollLogger::WARN_LOG,LocalRollLogger::ERROR_LOG + * @msg 日志内容语句,包括<<重定向符连接的语句,如 "Demo begin" << " testing !" <isNeedLog(level)) LOG->log(level)<<__VA_ARGS__;}while(0) +#else +#define LOGMSG(level,msg...) do{ if(LOG->isNeedLog(level)) LOG->log(level)<logger()->any()) +#define FDLOG(x) (RemoteTimeLogger::getInstance()->logger(x)->any()) +#define FFDLOG(x,y,z) (RemoteTimeLogger::getInstance()->logger(x,y,z)->any()) + +/** + * 按天日志局部使能开关,针对单个日志文件进行使能,请在所有按天日志输出前调用 + */ +#define TENREMOTE_FDLOG(swith,sApp,sServer,sFile) (RemoteTimeLogger::getInstance()->enableRemoteEx(sApp,sServer,sFile,swith)) +#define TENLOCAL_FDLOG(swith,sApp,sServer,sFile) (RemoteTimeLogger::getInstance()->enableLocalEx(sApp,sServer,sFile,swith)) + +/** + * 按天日志全局使能开关,请在所有按天日志输出前调用 + */ +#define TENREMOTE(swith) (RemoteTimeLogger::getInstance()->enableRemoteLog(swith)) +#define TENLOCAL(swith) (RemoteTimeLogger::getInstance()->enableLocalLog(swith)) +} + +#endif + diff --git a/servant/servant/TarsNotify.h b/servant/servant/RemoteNotify.h similarity index 95% rename from servant/servant/TarsNotify.h rename to servant/servant/RemoteNotify.h index 9b692cad0c3a436e23b4419d2f332bc11e3158d3..ce933e69eb247aeb8e6126ef9e28c322af0a7ba9 100644 --- a/servant/servant/TarsNotify.h +++ b/servant/servant/RemoteNotify.h @@ -30,7 +30,7 @@ namespace tars * 上报信息给Notify服务 * 异步上报给notify服务 */ -class TarsRemoteNotify : public TC_Singleton +class RemoteNotify : public TC_Singleton { public: /** @@ -43,7 +43,7 @@ public: * * @return int */ - int setNotifyInfo(const CommunicatorPtr &comm, const string &obj, const string & app, const string &serverName, const string &nodeName, const string &sSetName=""); + int setNotifyInfo(const CommunicatorPtr &comm, const string &obj, const string & app, const string &serverName, const string &sSetName, const string &nodeName); /** * 通知, 一定是异步上报的 diff --git a/servant/servant/Servant.h b/servant/servant/Servant.h index 91cb1abd90e42b06f27ac8260f3af411ab99fbd3..41f6160a1a5fcbe18f5f634188cb46f609c92d0e 100644 --- a/servant/servant/Servant.h +++ b/servant/servant/Servant.h @@ -22,7 +22,7 @@ #include "util/tc_thread_pool.h" #include "util/tc_cas_queue.h" #include "servant/ServantProxy.h" -#include "servant/TarsCurrent.h" +#include "servant/Current.h" #include "servant/BaseNotify.h" namespace tars @@ -250,7 +250,7 @@ protected: ServantPtr _servant; /* - * TarsCurrent + * Current */ TarsCurrentPtr _current; }; diff --git a/servant/servant/ServantHandle.h b/servant/servant/ServantHandle.h index 5e9b69e4de3780ba64ab82c81b2c0399debb031a..3dca37714df31187a0d42fc32ee5d8d7d06392dc 100644 --- a/servant/servant/ServantHandle.h +++ b/servant/servant/ServantHandle.h @@ -27,7 +27,7 @@ #include "servant/Servant.h" #include "servant/StatReport.h" #include "servant/CoroutineScheduler.h" -#ifdef _USE_OPENTRACKING +#ifdef TARS_OPENTRACKING #include "opentracing/span.h" #endif @@ -58,10 +58,10 @@ public: */ ~ServantHandle(); - /** - * 线程处理方法 - */ - virtual void run(); + /** + * 线程处理方法 + */ + virtual void run(); /** * 获取协程调度器 @@ -136,14 +136,14 @@ protected: /** * 创建上下文 * @param stRecvData - * @return TarsCurrent* + * @return Current* */ TarsCurrentPtr createCurrent(const shared_ptr &data); /** * 创建闭连接时的关上下文 * @param stRecvData - * @return TarsCurrent* + * @return Current* */ TarsCurrentPtr createCloseCurrent(const shared_ptr &data); @@ -161,14 +161,8 @@ protected: */ void handleNoTarsProtocol(const TarsCurrentPtr ¤t); - /** - * 处理TARS下的采样统计逻辑 - * - * @param current - */ - void processSample(const TarsCurrentPtr ¤t); -#ifdef _USE_OPENTRACKING +#ifdef TARS_OPENTRACKING /** * 处理TARS下的调用链逻辑 * @@ -186,6 +180,11 @@ protected: */ bool processDye(const TarsCurrentPtr ¤t, string& dyeingKey); + /** + * 处理cookie + */ + bool processCookie(const TarsCurrentPtr ¤t, map &cookie); + /** * 检查set调用合法性 * @@ -206,7 +205,7 @@ protected: */ CoroutineScheduler *_coroSched; -#ifdef _USE_OPENTRACKING +#ifdef TARS_OPENTRACKING map> _spanMap; #endif }; diff --git a/servant/servant/ServantHelper.h b/servant/servant/ServantHelper.h index eae8c24bdbf5fd689d6a60d656548403d9d3c56a..1e64461bbedca88eba4a9a17e68082771b6fc8f7 100644 --- a/servant/servant/ServantHelper.h +++ b/servant/servant/ServantHelper.h @@ -56,7 +56,7 @@ struct ServantCreation : public ServantHelperCreation /** * Servant管理 */ -class ServantHelperManager : public TC_Singleton +class SVT_DLL_API ServantHelperManager : public TC_Singleton { public: /** @@ -77,8 +77,8 @@ public: { if(check && _servant_adapter.end() == _servant_adapter.find(id)) { - cerr<<"[TAF]ServantHelperManager::addServant "<< id <<" not find adapter.(maybe not conf in the web)"<(application); } @@ -188,7 +188,7 @@ protected: /** * 是否染色 */ - bool _isDyeing; + bool _isDyeing; /** * 染色用户号码 diff --git a/servant/servant/ServantProxy.h b/servant/servant/ServantProxy.h index 800c941d6c96e78b55305830329114677501dc30..dd04e2ccb1bfd987e6bb565f94152d8182389d9d 100644 --- a/servant/servant/ServantProxy.h +++ b/servant/servant/ServantProxy.h @@ -21,7 +21,7 @@ #include "util/tc_autoptr.h" #include "servant/Message.h" #include "servant/AppProtocol.h" -#include "servant/TarsCurrent.h" +#include "servant/Current.h" //#include "servant/EndpointInfo.h" #include "servant/CommunicatorEpoll.h" @@ -148,9 +148,14 @@ public: * objectProxy Pointer */ shared_ptr _objectProxyOwn; //保存ObjectProxy对象的指针数组 -#ifdef _USE_OPENTRACKING +#ifdef TARS_OPENTRACKING std::unordered_map _trackInfoMap; #endif + + /** + * cookie + */ + map _cookie; // cookie内容 }; @@ -259,6 +264,12 @@ public: */ virtual ~ServantProxyCallback() {} + /** + * 设置发起调用的servant + * @param prx + */ + void setServantPrx(const ServantPrx &prx) { _servantPrx = prx; } + /** * 获取类型 * @return const string& @@ -283,7 +294,7 @@ public: /** * 异步请求是否在网络线程处理 - * tars内部用的到 业务不能设置这个值 + * taf内部用的到 业务不能设置这个值 * */ inline void setNetThreadProcess(bool bNetThreadProcess) { @@ -296,13 +307,32 @@ public: } public: + /** + * dispatch, call onDispatch + * @param msg + * @return + */ + int dispatch(ReqMessagePtr msg); + +protected: /** * 异步回调对象实现该方法,进行业务逻辑处理 * @param msg * @return int */ - virtual int onDispatch(ReqMessagePtr ptr) = 0; + virtual int onDispatch(ReqMessagePtr msg) = 0; + + /** + * 连接关闭掉了(push callback 才有效) + */ + virtual void onClose(){}; + /** + * 连接已建立(push callback 才有效) + */ + virtual void onConnect(const TC_Endpoint &ep){}; + + friend class Transceiver; protected: /** @@ -319,18 +349,20 @@ protected: /** * 协程并行请求的共享智能指针 */ - tars::CoroParallelBasePtr _pPtr; + CoroParallelBasePtr _pPtr; + + /** + * servant prx + */ + ServantPrx _servantPrx; }; /////////////////////////////////////////////////////////////////////////////////////////////// // for http class HttpCallback : public TC_HandleBase { public: - virtual int onHttpResponse(const std::map& requestHeaders , - const std::map& responseHeaders , - const std::vector& rspBody) = 0; - virtual int onHttpResponseException(const std::map& requestHeaders, - int expCode) = 0; + virtual int onHttpResponse(const shared_ptr &rsp) = 0; + virtual int onHttpResponseException(int expCode) = 0; }; typedef TC_AutoPtr HttpCallbackPtr; @@ -382,9 +414,9 @@ public: */ static string STATUS_DYED_KEY; //需要染色的用户ID - static string STATUS_GRID_KEY; //需要灰度的用户ID +// static string STATUS_GRID_KEY; //需要灰度的用户ID - static string STATUS_SAMPLE_KEY; //stat 采样的信息 +// static string STATUS_SAMPLE_KEY; //stat 采样的信息 static string STATUS_RESULT_CODE; //处理结果码,tup使用 @@ -392,16 +424,35 @@ public: static string STATUS_SETNAME_VALUE; //set调用 - static string TARS_MASTER_KEY; //透传主调名称信息 +// static string TARS_MASTER_KEY; //透传主调名称信息 static string STATUS_TRACK_KEY; //track信息 + // static string STATUS_COOKIE; //cookie信息 + /** * 缺省的同步调用超时时间 * 超时后不保证消息不会被服务端处理 */ enum { DEFAULT_SYNCTIMEOUT = 3000, DEFAULT_ASYNCTIMEOUT=5000}; + /** + * default connection serial num + */ + const static int DEFAULT_CONNECTION_SERIAL = 10; + + /** + * 内置四种协议支持 + */ + enum SERVANT_PROTOCOL + { + PROTOCOL_TARS, //默认tars服务的协议 + PROTOCOL_HTTP1, //http协议 +#if TARS_HTTP2 + PROTOCOL_HTTP2, //http2协议 +#endif + }; + /** * 构造函数 * @param op @@ -499,25 +550,60 @@ public: */ void tars_connect_timeout(int conTimeout); + /** + * set auto reconnect time + * @return int, second + */ + void tars_reconnect(int second); + /** * 获取所属的Object名称 * @return string */ string tars_name() const; + /** + * 获取所属的Object名称#hash@address + * @return string + */ + string tars_full_name() const; + /** * 获取最近一次调用的IP地址和端口 * @return string */ static TC_Endpoint tars_invoke_endpoint(); + /** + * 设置连接为多连接, 串行模式 + * @param connectionSerial, <=0: 连接复用模式(一个连接上同时跑多个请求, 响应包), >0: 连接串行模式(连接个数), 同一个连接上并行只能跑一个包(http协议) + */ + void tars_connection_serial(int connectionSerial); + + /** + * 获取连接并发模式 + * @return int + */ + int tars_connection_serial() const; + + /** + * 直接设置内置支持的协议 + */ + void tars_set_protocol(SERVANT_PROTOCOL protocol, int connectionSerial = 0); + /** * 设置用户自定义协议 * @param protocol */ - void tars_set_protocol(const ProxyProtocol& protocol); + void tars_set_protocol(const ProxyProtocol& protocol, int connectionSerial = 0); /** + * get protocol + * @return + */ + ProxyProtocol tars_get_protocol(); + + /** *设置套接字选项 */ void tars_set_sockopt(int level, int optname, const void *optval, SOCKET_LEN_TYPE optlen); @@ -620,42 +706,40 @@ public: // std::map& rheaders, // std::string& rbody); - /** - * http2协议同步远程调用 - */ - void http_call(const std::string& method, - const std::string& uri, - const std::map& headers, - const std::string& body, - std::map& rheaders, - std::string& rbody); - /** - * http2协议异步远程调用 - */ - void http_call_async(const std::string& method, - const std::string& uri, - const std::map& headers, - const std::string& body, - const HttpCallbackPtr &cb); + /** + * http1/2协议同步远程调用 + * @param funcName: 调用名称, 这里只是做统计用 + */ + void http_call(const string &funcName, shared_ptr &request, shared_ptr &response); + + /** + * http1/2协议异步远程调用 + * @param funcName: 调用名称, 这里只是做统计用 + */ + void http_call_async(const string &funcName, shared_ptr &request, const HttpCallbackPtr &cb, bool bCoro = false); /** - * 在RequestPacket中的context设置主调信息标识 + * TARS协议同步方法调用 */ - virtual void tars_setMasterFlag(bool bMasterFlag) {_masterFlag = bMasterFlag;} + shared_ptr tars_invoke(char cPacketType, + const string& sFuncName, + tars::TarsOutputStream& buf, + const map& context, + const map& status); /** * TARS协议同步方法调用 */ - virtual shared_ptr tars_invoke(char cPacketType, + shared_ptr tars_invoke(char cPacketType, const string& sFuncName, - tars::TarsOutputStream& buf, + const vector& buf, const map& context, const map& status); /** * TARS协议异步方法调用 */ - virtual void tars_invoke_async(char cPacketType, + void tars_invoke_async(char cPacketType, const string& sFuncName, tars::TarsOutputStream &buf, const map& context, @@ -663,6 +747,25 @@ public: const ServantProxyCallbackPtr& callback, bool bCoro = false); + /** + * TARS协议异步方法调用 + */ + void tars_invoke_async(char cPacketType, + const string& sFuncName, + const vector &buf, + const map& context, + const map& status, + const ServantProxyCallbackPtr& callback, + bool bCoro = false); + + /** + * 获得可以复用的servant + * @return + */ + ServantPrx getServantPrx(ReqMessage *msg); + + friend class ServantProxyCallback; + private: /** * 远程方法调用 @@ -671,6 +774,13 @@ private: */ void invoke(ReqMessage *msg, bool bCoroAsync = false); + /** + * 选择某个servant来发送 + * @param msg + * @param bCoroAsync + */ + int servant_invoke(ReqMessage *msg, bool bCoroAsync); + // /** // * invoke 异步 // * @param msg @@ -700,6 +810,24 @@ private: * @param req */ void checkDye(RequestPacket& req); + + /** + * 更新endpoint + * @param active + * @param inactive + */ + void onNotifyEndpoints(size_t netThreadSeq, const set & active,const set & inactive); + + /** + * 端口不活跃 + */ + void onSetInactive(const EndpointInfo& ep); + /** + * 检查是否需要设置cookie + * @param req + */ + void checkCookie(RequestPacket &req); + private: friend class ObjectProxy; friend class AdapterProxy; @@ -707,29 +835,29 @@ private: /** * 通信器 */ - Communicator * _communicator; + Communicator * _communicator; /** * 保存ObjectProxy对象的指针数组 */ - ObjectProxy ** _objectProxy; //保存ObjectProxy对象的指针数组 - shared_ptr _objectProxyOwn; //保存ObjectProxy对象的指针数组 + ObjectProxy ** _objectProxy; //保存ObjectProxy对象的指针数组 + shared_ptr _objectProxyOwn; //保存ObjectProxy对象的指针数组 /** * ObjectProxy对象的个数,其个数由客户端的网络线程数决定, * 每个网络线程有一个ObjectProxy */ - size_t _objectProxyNum; + size_t _objectProxyNum; /** * 同步调用超时(毫秒) */ - int _syncTimeout; + int _syncTimeout; /** * 同步调用超时(毫秒) */ - int _asyncTimeout; + int _asyncTimeout; /** * 唯一id @@ -750,6 +878,31 @@ private: *最小的超时时间 */ int64_t _minTimeout; + + /** + * 最大连接串行数(默认0, 表示连接并行请求) + */ + int _connectionSerial = 0; + + /** + * 短连接使用http使用 + */ + ServantPrx _rootPrx; + + /** + * + */ + int _servantId = 0; + + /** + * + */ + std::mutex _servantMutex; + + /** + * + */ + vector _servantList; }; } #endif diff --git a/servant/servant/StatReport.h b/servant/servant/StatReport.h index 9cdb5b72ea434f6f1f513ada40c72a6be7a00791..fe89b89abee9e344bb71345602095e653f505209 100644 --- a/servant/servant/StatReport.h +++ b/servant/servant/StatReport.h @@ -42,6 +42,11 @@ namespace tars { +/** + * 状态上报类, 上报的信息包括: + * 1 模块间调用的信息 + * 2 业务自定义的属性统计 + */ struct StatSampleMsgHead { string slaveName; @@ -219,17 +224,17 @@ public: */ StatFPrx getStatPrx() {return _statPrx; } - /* - * 采样 - */ - void doSample(const string& strSlaveName, - const string& strInterfaceName, - const string& strSlaveIp, - map &status); - /* - * 采样id - */ - string sampleUnid(); +// /* +// * 采样 +// */ +// void doSample(const string& strSlaveName, +// const string& strInterfaceName, +// const string& strSlaveIp, +// map &status); +// /* +// * 采样id +// */ +// string sampleUnid(); /** * 增加关注时间点. 调用方式addStatInterv(5) @@ -306,21 +311,27 @@ private: */ int reportPropMsg(); - /** - * 上报多维度属性信息 Prop = property - * @return int - */ - int reportPropPlusMsg(); +// /** +// * 上报多维度属性信息 Prop = property +// * @return int +// */ +// int reportPropPlusMsg(); /** * stat 采样 */ int reportSampleMsg(); - //合并两个MicMsg void addMicMsg(MapStatMicMsg & old,MapStatMicMsg & add); + /** + * get queue info + * @return + */ + size_t getQueueSize(size_t epollIndex); + + friend class CommunicatorEpoll; private: time_t _time; diff --git a/servant/servant/TarsLogger.h b/servant/servant/TarsLogger.h index 264586036cf3f8abc88e60c355bc7e711b2b9755..b3f2a66e3d53dd7708c57b803f541aead6db1cd0 100755 --- a/servant/servant/TarsLogger.h +++ b/servant/servant/TarsLogger.h @@ -1,893 +1,3 @@ -/** - * Tencent is pleased to support the open source community by making Tars available. - * - * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * Unless required by applicable law or agreed to in writing, software distributed - * under the License is distributed on an "AS IS" BASIS, WITHOUT 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 __TARS_LOGGER_H__ -#define __TARS_LOGGER_H__ - -#include "util/tc_logger.h" -#include "util/tc_file.h" -#include "util/tc_singleton.h" -#include "servant/Global.h" -#include "servant/LogF.h" -#include "servant/PropertyReport.h" - -#define DYEING_DIR "tars_dyeing" -#define DYEING_FILE "dyeing" - -namespace tars -{ - -/** - * LOG的库说明: - * 1 循环日志采用TLOGERROR(...),TLOGDEBUG(...) - * 2 循环日志不上传到服务器 - * 3 按天日志采用DLOG, FDLOG来记录 - * 4 按天日志也可以不上传到远程服务器:DLOG("")->disableRemote(); - * 5 按天日志可以改变每天一个文件的方式: - * DLOG("abc3")->setFormat("%Y%m%d%H"); - * 每个小时一个文件 - */ - -/***************************************************************************** -实现方式说明(只介绍按时间的日志, 会写到tarslog): - 1 自定义时间日志的WriteT类:RemoteTimeWriteT - 2 在RemoteTimeWriteT类中, 写入到远程 - 3 定义远程日志类:typedef TC_Logger RemoteTimeLogger; - 4 为了保证远程的写日志也是在单独线程处理,重新定义本地按天日志类 - 5 自定义时间日志的WriteT类:TimeWriteT - 6 在TimeWriteT类中包含RemoteTimeLogger对象 - 7 在TimeWriteT类的写入操作中, 写入本地文件后, 同时写入到RemoteTimeLogger对象中 - 8 RemoteTimeLogger会在RemoteTimeWriteT对象中, 异步写入到远程 - 9 从而本地文件写和远程写不在一个线程中. -*****************************************************************************/ - -/////////////////////////////////////////////////////////////////////////////// - -class RollWriteT -{ -public: - RollWriteT(); - ~RollWriteT(); - - void operator()(ostream &of, const deque > &ds); - - void setDyeingLogInfo(const string &sApp, const string &sServer, const string & sLogPath, - int iMaxSize, int iMaxNum, const CommunicatorPtr &comm, const string & sLogObj); - -protected: - - TC_RollLogger *_dyeingRollLogger; - - static int _dyeingThread; - - string _app; - string _server; - string _logPath; - int _maxSize; - int _maxNum; - - /** - * 染色远程滚动日志代理 - */ - LogPrx _logPrx; - - -}; - - -/** - * 本地日志帮助类, 单件 - * 循环日志单件是永生不死的, 保证任何地方都可以使用 - * 当该对象析够以后, 则直接cout出来 - */ -class TarsRollLogger : public TC_Singleton -{ -public: - enum - { - NONE_LOG = 1, /**所有的log都不写*/ - ERROR_LOG = 2, /**写错误log*/ - WARN_LOG = 3, /**写错误,警告log*/ - DEBUG_LOG = 4, /**写错误,警告,调试log*/ - INFO_LOG = 5, /**写错误,警告,调试,Info log*/ - TARS_LOG = 6 /**写错误,警告,调试,Info log*/ - }; -public: - typedef TC_Logger RollLogger; - - /** - * 设置本地信息 - * @param app, 业务名称 - * @param server, 服务名称 - * @param logpath, 日志路径 - * @param iMaxSize, 文件最大大小,字节 - * @param iMaxNum, 文件最大数 - */ - void setLogInfo(const string &sApp, const string &sServer, const string &sLogpath, int iMaxSize = 1024*1024*50, int iMaxNum = 10, const CommunicatorPtr &comm=NULL, const string &sLogObj=""); - - /** - * 设置同步写日志 - * - * @param bSync - */ - void sync(bool bSync = true); - - /** - * 获取循环日志 - * - * @return RollLogger - */ - RollLogger *logger() { return &_logger; } - - /** - * 染色日志是否启用 - * @param bEnable - */ - void enableDyeing(bool bEnable, const string& sDyeingKey = ""); - -protected: - - /** - * 应用 - */ - string _app; - - /** - * 服务名称 - */ - string _server; - - /** - * 日志路径 - */ - string _logpath; - - /** - * 循环日志 - */ - RollLogger _logger; - - /** - * 本地线程组 - */ - TC_LoggerThreadGroup _local; - -}; - -/////////////////////////////////////////////////////////////////////////////////////// -// -/** - * 写日志线程 - * 将写本地日志和远程分开到不同的线程 - * 作为单件存在, 且是永生不死的单件 - */ -class TarsLoggerThread : public TC_Singleton -{ -public: - /** - * 构造函数 - */ - TarsLoggerThread(); - - /** - * 析够函数 - */ - ~TarsLoggerThread(); - - /** - * 本地写日志线程 - */ - TC_LoggerThreadGroup* local(); - - /** - * 远程写日志线程 - * - * @return TC_LoggerThreadGroup* - */ - TC_LoggerThreadGroup* remote(); - -protected: - - /** - * 本地线程组 - */ - TC_LoggerThreadGroup _local; - - /** - * 远程写线程组 - */ - TC_LoggerThreadGroup _remote; -}; - -/////////////////////////////////////////////////////////////////////////////////////// -class TimeWriteT; - -/** - * 远程的Log写操作类 - */ -class RemoteTimeWriteT -{ -public: - RemoteTimeWriteT(); - ~RemoteTimeWriteT(); - - /** - * 构造函数 - */ - void setTimeWriteT(TimeWriteT *pTimeWrite); - - /** - * 具体调用 - * @param of - * @param buffer - */ - void operator()(ostream &of, const deque > &buffer); - -protected: - /** - * 同步到远程 - */ - void sync2remote(const vector &buffer); - - /** - * 染色日志同步到远程 - */ - void sync2remoteDyeing(const vector &buffer); - -protected: - /** - * 指针 - */ - TimeWriteT *_timeWrite; - -}; - -//////////////////////////////////////////////////////////////////////////// -/** - * 写Logger - */ -class TimeWriteT -{ -public: - typedef TC_Logger RemoteTimeLogger; - - typedef TC_Logger DyeingTimeLogger; - - /** - * 构造 - */ - TimeWriteT(); - - /** - * 析够 - */ - ~TimeWriteT(); - - /** - * 设置基本信息 - * @param app, 应用名称 - * @param server, 服务名称 - * @param file, 日志文件名 - * @param sFormat, 格式 - * @param setdivision,set名称 - * @param sLogType,日志记录类型 - */ - void setLogInfo(const LogPrx &logPrx, const string &sApp, const string &sServer, const string &sFile, const string &sLogpath, const string &sFormat, const string& setdivision = "", const string& sLogType = "", const PropertyReportPtr &reportSuccPtr = NULL, const PropertyReportPtr &reportFailPtr = NULL); - - /** - * 设置代理 - * @param logPrx 代理信息 - */ - void setLogPrx(const LogPrx &logPrx); - - /** - * 远程日志功能打开或关闭 - * @param bEnable - */ - void enableRemote(bool bEnable) { _remote = bEnable; } - - /** - * 本地日志功能功能打开或关闭 - * @param bEnable - */ - void enableLocal(bool bEnable); - - /** - * 染色日志功能打开或关闭 - * @param bEnable - */ - void enableDyeing (bool bEnable, const string& sDyeingKey = ""); - - - /** - * @brief 日志文件名是否带.log后缀 - * @param bEnable - */ - void enableSufix(bool bEnable=true){_hasSufix = bEnable;} - /** - * @brief 是否允许框架在日志文件名上增加业务相关的标识 - * @param bEnable - */ - void enablePrefix(bool bEnable=true){_hasAppNamePrefix = bEnable;} - /** - * @brief 日志文件名中用户自定义字符与日期字符间的连接符,默认是"_" - * @param str - */ - void setFileNameConcatStr(const string& str) {_concatStr = str;} - - /** - * @brief 框架中增加的日志内容之间的分割符,默认是"|" - * @param str - */ - void setSeparator(const string& str) {_separ = str;} - - /** - * @brief 框架中日期和时间之间是否需要加中括号[],有些统计由特殊需求;默认不加 - * @param bEnable - */ - void enableSqareWrapper(bool bEnable) {_hasSquareBracket = bEnable;} - - - /** - * 设置时间格式("%Y%m%d") - * @param sFormat - */ - void setFormat(const string &sFormat) { _format = sFormat;} - - /** - * 具体调用 - * @param of - * @param buffer - */ - void operator()(ostream &of, const deque > &buffer); - -protected: - - /** - * 友元 - */ - friend class RemoteTimeWriteT; - - /** - * 记录错误文件 - * @param buffer - */ - void writeError(const vector &buffer); - - /** - * 记录错误文件 - * @param buffer - */ - void writeError(const deque > &buffer); - - /** - * 初始化logger - */ - void initError(); - - /** - * 初始化染色日志 - */ - void initDyeingLog(); - -protected: - - /** - * 远程时间日志 - */ - RemoteTimeLogger *_remoteTimeLogger; - - /** - * 本地功能 - */ - bool _local; - - /** - * 远程功能 - */ - bool _remote; - - /** - * 远程服务句柄 - */ - LogPrx _logPrx; - - /** - * app名称 - */ - string _app; - - /** - * 服务名称 - */ - string _server; - - /** - * 日志文件名称 - */ - string _file; - - /** - * 时间格式 - */ - string _format; - - /** - * 具体文件 - */ - string _filePath; - - /** - * 错误文件 - */ - TC_DayLogger _logger; - - /** - * 缺省写模式 - */ - TC_DefaultWriteT _wt; - - /** - * 染色日志 - */ - static int _dyeing; - - /** - * 染色日志目录路径 - */ - string _dyeingFilePath; - - /** - * 远程时间日志 - */ - DyeingTimeLogger *_dyeingTimeLogger; - - /** - * set分组信息 - */ - string _setDivision; - - /** - * 日志文件名是否带.log后缀 - */ - bool _hasSufix; - /** - * 是否允许框架在日志文件名上增加业务相关的标识 - */ - bool _hasAppNamePrefix; - - /** - * 日志文件名中用户自定义字符与日期字符间的连接符,默认是"_" - */ - string _concatStr; - /** - * 分隔符 - */ - string _separ; - /** - * 日期部分是否加上[] - */ - bool _hasSquareBracket; - - /* - * 本地日志的记录类型,格式为TarsLogType.toString()返回值,如果不采用TarsLogType,则该值为"" - */ - string _logType; - - /* - * 对于远程日志,上报同步到logser的成功量,默认不上报 - */ - PropertyReportPtr _reportSuccPtr; - - /* - * 对于远程日志,上报同步到logser的失败量,默认不上报 - */ - PropertyReportPtr _reportFailPtr; -}; - -//////////////////////////////////////////////////////////////////////////// -/** - * 远程日志帮助类, 单件 - */ -class TarsTimeLogger : public TC_HandleBase - , public TC_ThreadLock - , public TC_Singleton -{ -public: - - //定义按时间滚动的日志 - typedef TC_Logger TimeLogger; - - /** - * 构造 - */ - TarsTimeLogger(); - - /** - * 析够 - */ - ~TarsTimeLogger(); - - /** - * 设置本地信息 - * @param comm, 通信器 - * @param obj, 日志对象名称 - * @param app, 业务名称 - * @param server, 服务名称 - * @param logpath, 日志路径 - */ - void setLogInfo(const CommunicatorPtr &comm, const string &obj, const string &sApp, const string &sServer, const string &sLogpath,const string& setdivision="", const bool &bLogStatReport = false); - - /** - * 初始化设置时间格式("%Y%m%d") - * 不要动态修改, 线程不安全 - * 如果有需要, 初始化后直接修改 - * @param sFormat, 文件名称, 为空表示缺省的时间日志 - */ - void initFormat(const string &sFile, const string &sFormat,const TarsLogTypePtr& logTypePtr=NULL); - void initFormat(const string &sApp, const string &sServer,const string &sFile, const string &sFormat,const TarsLogTypePtr& logTypePtr=NULL); - /** - * 初始化设置时间格式("%Y%m%d") - * 不要动态修改, 线程不安全 - * 如果有需要, 初始化后直接修改 - * @param sFormat, 文件名称, 为空表示缺省的时间日志 - * @param frequency 支持每多少天/小时/分钟,详见TC_logger.h中关于TarsLogByDay,TarsLogByHour,TarsLogByMinute的描述 - * - * 用法: 按两个小时记录日志 - * initFormat("logfile",TarsLogByHour::FORMAT,2); - */ - template - void initFormatWithType(const string &sFile, const string &sFormat,size_t frequency) - { - TarsLogTypePtr logTypePtr = new TarsLogType(sFormat,frequency); - initFormat(sFile,sFormat,logTypePtr); - } - - template - void initFormatWithType(const string &sApp, const string &sServer,const string &sFile, const string &sFormat,size_t frequency) - { - TarsLogTypePtr logTypePtr = new TarsLogType(sFormat,frequency); - initFormat(sApp,sServer,sFile,sFormat,logTypePtr); - } - /** - * 获取时间日志 - * @param file - */ - TimeLogger *logger(const string &sFile = ""); - - /** - * 获取时间日志 - * @param app, 业务名称 - * @param server, 服务名称 - * @param file - */ - TimeLogger *logger(const string &sApp, const string &sServer,const string &sFile = ""); - - /** - * 同步写本地时间日志(远程日志一定是异步写的, 无法调整) - * @param bSync - */ - void sync(const string &sFile, bool bSync); - - /** - * 远程时间日志 - * @param sFile, 文件名称, 为空表示缺省的时间日志 - * @param bEnable - */ - void enableRemote(const string &sFile, bool bEnable); - - /** - * 远程时间日志 - * @param sApp,应用名称 - * @param sServer,服务名称 - * @param sFile, 文件名称, 为空表示缺省的时间日志 - * @param bEnable - */ - void enableRemoteEx(const string &sApp, const string &sServer,const string &sFile, bool bEnable); - /** - * 本地时间日志 - * @param sFile,文件名称, 为空表示缺省的时间日志 - * @param bEnable - */ - void enableLocal(const string &sFile, bool bEnable); - /** - * 本地时间日志 - * @param sApp,应用名称 - * @param sServer,服务名称 - * @param sFile, 文件名称, 为空表示缺省的时间日志 - * @param bEnable - */ - void enableLocalEx(const string &sApp, const string &sServer,const string &sFile, bool bEnable); - - /** - * @brief 日志文件名是否带.log后缀,影响全部日志文件 - * @param bEnable - */ - void enableSufix(bool bEnable=true){_hasSufix = bEnable;} - /** - * @brief 是否允许框架在日志文件名上增加业务相关的标识,影响全部日志文件 - * @param bEnable - */ - void enablePrefix(bool bEnable=true){_hasAppNamePrefix = bEnable;} - /** - * @brief 日志文件名中用户自定义字符与日期字符间的连接符,默认是"_",影响全部日志文件 - * @param str - */ - void setFileNameConcatStr(const string& str) {_concatStr = str;} - - /** - * @brief 框架中增加的日志内容之间的分割符,默认是"|",影响全部日志文件 - * @param str - */ - void setSeparator(const string& str) {_separ = str;} - - /** - * @brief 框架中日期和时间之间是否需要加中括号[],有些统计由特殊需求;默认不加,影响全部日志文件 - * @param bEnable - */ - void enableSqareWrapper(bool bEnable) {_hasSquareBracket = bEnable;} - /** - * @brief 是否输出本地日志文件,影响全部日志文件 - * @param bEnable - */ - void enableLocalLog(bool bEnable) {_local = bEnable;} - /** - * @brief 是否输出远程日志文件,影响全部日志文件 - * @param bEnable - */ - void enableRemoteLog(bool bEnable) {_remote = bEnable;} -protected: - - /** - * 初始化时间日志 - * @param pTimeLogger - * @param sFile - * @param sFormat - * @param frequence, 每多少天/小时/分钟,单位是秒 - */ - void initTimeLogger(TimeLogger *pTimeLogger, const string &sFile, const string &sFormat,const TarsLogTypePtr& logTypePtr=NULL); - - /** - * 初始化时间日志 - * @param pTimeLogger - * @param sApp - * @param sServer - * @param sFile - * @param sFormat - * @param frequence, 每多少天/小时/分钟,单位是秒 - */ - - void initTimeLogger(TimeLogger *pTimeLogger,const string &sApp, const string &sServer, const string &sFile, const string &sFormat,const TarsLogTypePtr& logTypePtr=NULL); - -protected: - - /** - * 通信器 - */ - CommunicatorPtr _comm; - - /** - * 远程服务句柄 - */ - LogPrx _logPrx; - - /** - * 应用 - */ - string _app; - - /** - * 服务名称 - */ - string _server; - - /** - * 日志路径 - */ - string _logpath; - - /** - * 缺省按天日志 - */ - TimeLogger *_defaultLogger; - - /** - * 远程日志 - */ - map _loggers; - /** - * set分组信息 - */ - string _setDivision; - - /** - * 是否带.log后缀 - */ - bool _hasSufix; - /** - * 是否允许框架在日志文件名上增加业务相关的标识 - */ - bool _hasAppNamePrefix; - - /** - * 日志文件名中用户自定义字符与日期字符间的连接符,默认是"_" - */ - string _concatStr; - /** - * 分隔符 - */ - string _separ; - /** - * 日期部分是否加上[] - */ - bool _hasSquareBracket; - /** - * 是否输出本地日志 - */ - bool _local; - /** - * 是否输出远程日志 - */ - bool _remote; - - /* - * 服务日志上报logser是否上报成功数量 - */ - bool _logStatReport; -}; - -/** - * 染色开关类,析构时关闭 - */ -class TarsDyeingSwitch -{ -public: - /** - * 构造函数,默认不打开染色日志 - */ - TarsDyeingSwitch() - :_needDyeing(false) - { - } - - /** - * 析构函数,关闭已打开的染色日志 - */ - ~TarsDyeingSwitch() - { - if(_needDyeing) - { - TarsRollLogger::getInstance()->enableDyeing(false); - - ServantProxyThreadData * td = ServantProxyThreadData::getData(); - assert(NULL != td); - if (td) - { - td->_dyeing = false; - td->_dyeingKey = ""; - } - } - } - - /** - * 获取染色的key - * - * @param key - * @return bool - */ - static bool getDyeingKey(string & sDyeingkey) - { - ServantProxyThreadData * td = ServantProxyThreadData::getData(); - assert(NULL != td); - - if (td && td->_dyeing == true) - { - sDyeingkey = td->_dyeingKey; - return true; - } - return false; - } - - /** - * 启用染色日志 - */ - void enableDyeing(const string & sDyeingKey = "") - { - TarsRollLogger::getInstance()->enableDyeing(true); - - ServantProxyThreadData * td = ServantProxyThreadData::getData(); - assert(NULL != td); - if(td) - - { - td->_dyeing = true; - td->_dyeingKey = sDyeingKey; - } - _needDyeing = true; - _dyeingKey = sDyeingKey; - } - -protected: - bool _needDyeing; - string _dyeingKey; -}; - -/** - * 循环日志 - */ -#define LOG (TarsRollLogger::getInstance()->logger()) - -/** - * @brief 按级别循环日志宏 - * - * @param level 日志等级,TarsRollLogger::INFO_LOG,TarsRollLogger::DEBUG_LOG,TarsRollLogger::WARN_LOG,TarsRollLogger::ERROR_LOG - * @msg 日志内容语句,包括<<重定向符连接的语句,如 "Demo begin" << " testing !" <isNeedLog(level)) LOG->log(level)<<__VA_ARGS__;}while(0) -#else -#define LOGMSG(level,msg...) do{ if(LOG->isNeedLog(level)) LOG->log(level)<logger()->any()) -#define FDLOG(x) (TarsTimeLogger::getInstance()->logger(x)->any()) -#define FFDLOG(x,y,z) (TarsTimeLogger::getInstance()->logger(x,y,z)->any()) - -/** - * 按天日志局部使能开关,针对单个日志文件进行使能,请在所有按天日志输出前调用 - */ -#define TENREMOTE_FDLOG(swith,sApp,sServer,sFile) (TarsTimeLogger::getInstance()->enableRemoteEx(sApp,sServer,sFile,swith)) -#define TENLOCAL_FDLOG(swith,sApp,sServer,sFile) (TarsTimeLogger::getInstance()->enableLocalEx(sApp,sServer,sFile,swith)) - -/** - * 按天日志全局使能开关,请在所有按天日志输出前调用 - */ -#define TENREMOTE(swith) (TarsTimeLogger::getInstance()->enableRemoteLog(swith)) -#define TENLOCAL(swith) (TarsTimeLogger::getInstance()->enableLocalLog(swith)) -} - -#endif + +#include "RemoteLogger.h" diff --git a/servant/servant/Transceiver.h b/servant/servant/Transceiver.h index 1c5dd174a5079e9900096058374f594ff03cc1bc..59c19ea143d8365ce55df6d6fc24012efbd6d7ed 100755 --- a/servant/servant/Transceiver.h +++ b/servant/servant/Transceiver.h @@ -183,8 +183,8 @@ public: /* * 获取端口信息 */ - EndpointInfo& getEndpointInfo() - { + const EndpointInfo& getEndpointInfo() const + { return _ep; } diff --git a/servant/tup/Tars.h b/servant/tup/Tars.h index 75d2f641250b510079f4cc7f7b91a0b64f1763df..57747429656d0743f7e287cf40ca52f164f58eee 100755 --- a/servant/tup/Tars.h +++ b/servant/tup/Tars.h @@ -3,14 +3,14 @@ * * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. * - * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * https://opensource.org/licenses/BSD-3-Clause * - * Unless required by applicable law or agreed to in writing, software distributed - * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ @@ -37,9 +37,9 @@ //支持iphone #ifdef __APPLE__ - #include "TarsType.h" +#include "TarsType.h" #elif defined ANDROID // android - #include "TarsType.h" +#include "TarsType.h" #else #include "tup/TarsType.h" #endif @@ -355,293 +355,299 @@ do { \ namespace tars { ////////////////////////////////////////////////////////////////// - struct TarsStructBase - { - protected: - TarsStructBase() {} - - ~TarsStructBase() {} - }; - - struct TarsProtoException : public std::runtime_error - { - TarsProtoException(const std::string& s) : std::runtime_error(s) {} - }; - - struct TarsEncodeException : public TarsProtoException - { - TarsEncodeException(const std::string& s) : TarsProtoException(s) {} - }; - - struct TarsDecodeException : public TarsProtoException - { - TarsDecodeException(const std::string& s) : TarsProtoException(s) {} - }; - - struct TarsDecodeMismatch : public TarsDecodeException - { - TarsDecodeMismatch(const std::string & s) : TarsDecodeException(s) {} - }; - - struct TarsDecodeRequireNotExist : public TarsDecodeException - { - TarsDecodeRequireNotExist(const std::string & s) : TarsDecodeException(s) {} - }; - - struct TarsDecodeInvalidValue : public TarsDecodeException - { - TarsDecodeInvalidValue(const std::string & s) : TarsDecodeException(s) {} - }; - - struct TarsNotEnoughBuff : public TarsProtoException - { - TarsNotEnoughBuff(const std::string & s) : TarsProtoException(s) {} - }; +struct TarsStructBase +{ +protected: + TarsStructBase() {} + + ~TarsStructBase() {} +}; + +struct TarsProtoException : public std::runtime_error +{ + TarsProtoException(const std::string& s) : std::runtime_error(s) {} +}; + +struct TarsEncodeException : public TarsProtoException +{ + TarsEncodeException(const std::string& s) : TarsProtoException(s) {} +}; + +struct TarsDecodeException : public TarsProtoException +{ + TarsDecodeException(const std::string& s) : TarsProtoException(s) {} +}; + +struct TarsDecodeMismatch : public TarsDecodeException +{ + TarsDecodeMismatch(const std::string & s) : TarsDecodeException(s) {} +}; + +struct TarsDecodeRequireNotExist : public TarsDecodeException +{ + TarsDecodeRequireNotExist(const std::string & s) : TarsDecodeException(s) {} +}; + +struct TarsDecodeInvalidValue : public TarsDecodeException +{ + TarsDecodeInvalidValue(const std::string & s) : TarsDecodeException(s) {} +}; + +struct TarsNotEnoughBuff : public TarsProtoException +{ + TarsNotEnoughBuff(const std::string & s) : TarsProtoException(s) {} +}; ////////////////////////////////////////////////////////////////// - namespace - { - /// 数据头信息的封装,包括类型和tag - class DataHead - { - uint8_t _type; - uint8_t _tag; - public: - enum - { - eChar = 0, - eShort = 1, - eInt32 = 2, - eInt64 = 3, - eFloat = 4, - eDouble = 5, - eString1 = 6, - eString4 = 7, - eMap = 8, - eList = 9, - eStructBegin = 10, - eStructEnd = 11, - eZeroTag = 12, - eSimpleList = 13, - }; - - #pragma pack(1) - struct helper - { - uint8_t type : 4; - uint8_t tag : 4; - }; - #pragma pack() - public: - DataHead() : _type(0), _tag(0) {} - DataHead(uint8_t type, uint8_t tag) : _type(type), _tag(tag) {} - - uint8_t getTag() const { return _tag;} - void setTag(uint8_t t) { _tag = t;} - uint8_t getType() const { return _type;} - void setType(uint8_t t) { _type = t;} - - /// 读取数据头信息 - template - void readFrom(InputStreamT& is) - { - size_t n = peekFrom(is); - is.skip(n); - } - - /// 读取头信息,但不前移流的偏移量 - template - size_t peekFrom(InputStreamT& is) - { - helper h; - size_t n = sizeof(h); - is.peekBuf(&h, sizeof(h)); - _type = h.type; - if (h.tag == 15) - { - is.peekBuf(&_tag, sizeof(_tag), sizeof(h)); - n += sizeof(_tag); - } - else - { - _tag = h.tag; - } - return n; - } - - /// 写入数据头信息 - template - void writeTo(OutputStreamT& os) - { - /* - helper h; - h.type = _type; - if(_tag < 15){ - h.tag = _tag; - os.writeBuf(&h, sizeof(h)); - }else{ - h.tag = 15; - os.writeBuf(&h, sizeof(h)); - os.writeBuf(&_tag, sizeof(_tag)); - } - */ - writeTo(os, _type, _tag); - } - - /// 写入数据头信息 - template - static void writeTo(OutputStreamT& os, uint8_t type, uint8_t tag) - { - helper h; - h.type = type; - if (tag < 15) - { - h.tag = tag; - os.writeBuf(&h, sizeof(h)); - } - else - { - h.tag = 15; - os.writeBuf(&h, sizeof(h)); - os.writeBuf(&tag, sizeof(tag)); - } - } - }; - } +namespace +{ +/// 数据头信息的封装,包括类型和tag +class DataHead +{ + uint8_t _type; + uint8_t _tag; +public: + enum + { + eChar = 0, + eShort = 1, + eInt32 = 2, + eInt64 = 3, + eFloat = 4, + eDouble = 5, + eString1 = 6, + eString4 = 7, + eMap = 8, + eList = 9, + eStructBegin = 10, + eStructEnd = 11, + eZeroTag = 12, + eSimpleList = 13, + }; + +#pragma pack(1) + struct helper + { + uint8_t type : 4; + uint8_t tag : 4; + }; +#pragma pack() +public: + DataHead() : _type(0), _tag(0) {} + DataHead(uint8_t type, uint8_t tag) : _type(type), _tag(tag) {} + + uint8_t getTag() const { return _tag;} + void setTag(uint8_t t) { _tag = t;} + uint8_t getType() const { return _type;} + void setType(uint8_t t) { _type = t;} + + /// 读取数据头信息 + template + void readFrom(InputStreamT& is) + { + size_t n = peekFrom(is); + is.skip(n); + } + + /// 读取头信息,但不前移流的偏移量 + template + size_t peekFrom(InputStreamT& is) + { + helper h; + size_t n = sizeof(h); + is.peekBuf(&h, sizeof(h)); + _type = h.type; + if (h.tag == 15) + { + is.peekBuf(&_tag, sizeof(_tag), sizeof(h)); + n += sizeof(_tag); + } + else + { + _tag = h.tag; + } + return n; + } + + /// 写入数据头信息 + template + void writeTo(OutputStreamT& os) + { + /* + helper h; + h.type = _type; + if(_tag < 15){ + h.tag = _tag; + os.writeBuf(&h, sizeof(h)); + }else{ + h.tag = 15; + os.writeBuf(&h, sizeof(h)); + os.writeBuf(&_tag, sizeof(_tag)); + } + */ + writeTo(os, _type, _tag); + } + + /// 写入数据头信息 + template + static void writeTo(OutputStreamT& os, uint8_t type, uint8_t tag) + { + helper h; + h.type = type; + if (tag < 15) + { + h.tag = tag; + os.writeBuf((const char *)&h, sizeof(h)); + } + else + { + h.tag = 15; + os.writeBuf((const char *)&h, sizeof(h)); + os.writeBuf((const char *)&tag, sizeof(tag)); + } + } +}; +} ////////////////////////////////////////////////////////////////// /// 缓冲区读取器封装 - class BufferReader - { - private: - BufferReader(const BufferReader&); - - BufferReader& operator=(const BufferReader&); - - public: - const char * _buf; ///< 缓冲区 - size_t _buf_len; ///< 缓冲区长度 - size_t _cur; ///< 当前位置 - - public: - - BufferReader() : _buf(NULL),_buf_len(0),_cur(0) {} - - void reset() { _cur = 0;} - - /// 读取缓存 - void readBuf(void * buf, size_t len) - { - if(len <= _buf_len && (_cur + len) <= _buf_len) - { - peekBuf(buf, len); - _cur += len; - } - else - { - char s[64]; - snprintf(s, sizeof(s), "buffer overflow when skip, over %u.", (uint32_t)_buf_len); - throw TarsDecodeException(s); - } - } - - /// 读取缓存,但不改变偏移量 - void peekBuf(void * buf, size_t len, size_t offset = 0) - { - if (_cur + offset + len > _buf_len) - { - char s[64]; - snprintf(s, sizeof(s), "buffer overflow when peekBuf, over %u.", (uint32_t)_buf_len); - throw TarsDecodeException(s); - } - ::memcpy(buf, _buf + _cur + offset, len); - } - - /// 读取缓存 for vector - template - void readBuf(std::vector& v, size_t len) - { - if(len <= _buf_len && (_cur + len) <= _buf_len) - { - peekBuf(v, len); - _cur += len; - } - else - { - char s[64]; - snprintf(s, sizeof(s), "buffer overflow when skip, over %u.", (uint32_t)_buf_len); - throw TarsDecodeException(s); - } - } - - /// 读取缓存,但不改变偏移量 for vector - template - void peekBuf(std::vector& v, size_t len, size_t offset = 0) - { - if (_cur + offset + len > _buf_len) - { - char s[64]; - snprintf(s, sizeof(s), "buffer overflow when peekBuf, over %u.", (uint32_t)_buf_len); - throw TarsDecodeException(s); - } - - const char* begin = _buf + _cur + offset; - v.assign(begin, begin + len); - } - - /// 跳过len个字节 - void skip(size_t len) - { - if(len <= _buf_len && (_cur + len) <= _buf_len) - { - _cur += len; - } - else - { - char s[64]; - snprintf(s, sizeof(s), "buffer overflow when skip, over %u.", (uint32_t)_buf_len); - throw TarsDecodeException(s); - } - } - - /// 设置缓存 - void setBuffer(const char * buf, size_t len) - { - _buf = buf; - _buf_len = len; - _cur = 0; - } - - /// 设置缓存 - template - void setBuffer(const std::vector &buf) - { - _buf = buf.data(); - _buf_len = buf.size(); - _cur = 0; - } - - /** - * 判断是否已经到BUF的末尾 - */ - bool hasEnd() - { - return _cur >= _buf_len; - } - size_t tellp() const - { - return _cur; - } - const char* base() const - { - return _buf; - } - size_t size() const - { - return _buf_len; - } - }; +class BufferReader +{ +private: + BufferReader(const BufferReader&); + + BufferReader& operator=(const BufferReader&); + +public: + const char * _buf; ///< 缓冲区 + size_t _buf_len; ///< 缓冲区长度 + size_t _cur; ///< 当前位置 + +public: + + BufferReader() : _buf(NULL),_buf_len(0),_cur(0) {} + + void reset() { _cur = 0;} + + /// 读取缓存 + void readBuf(void * buf, size_t len) + { + if(len <= _buf_len && (_cur + len) <= _buf_len) + { + peekBuf(buf, len); + _cur += len; + } + else + { + char s[64]; + snprintf(s, sizeof(s), "buffer overflow when skip, over %u.", (uint32_t)_buf_len); + throw TarsDecodeException(s); + } + } + + /// 读取缓存,但不改变偏移量 + void peekBuf(void * buf, size_t len, size_t offset = 0) + { + if (_cur + offset + len > _buf_len) + { + char s[64]; + snprintf(s, sizeof(s), "buffer overflow when peekBuf, over %u.", (uint32_t)_buf_len); + throw TarsDecodeException(s); + } + ::memcpy(buf, _buf + _cur + offset, len); + } + + /// 读取缓存 for vector + template + void readBuf(std::vector& v, size_t len) + { + if(len <= _buf_len && (_cur + len) <= _buf_len) + { + peekBuf(v, len); + _cur += len; + } + else + { + char s[64]; + snprintf(s, sizeof(s), "buffer overflow when skip, over %u.", (uint32_t)_buf_len); + throw TarsDecodeException(s); + } + } + + /// 读取缓存,但不改变偏移量 for vector + template + void peekBuf(std::vector& v, size_t len, size_t offset = 0) + { + if (_cur + offset + len > _buf_len) + { + char s[64]; + snprintf(s, sizeof(s), "buffer overflow when peekBuf, over %u.", (uint32_t)_buf_len); + throw TarsDecodeException(s); + } + + const char* begin = _buf + _cur + offset; + v.assign(begin, begin + len); + } + + /// 跳过len个字节 + void skip(size_t len) + { + if(len <= _buf_len && (_cur + len) <= _buf_len) + { + _cur += len; + } + else + { + char s[64]; + snprintf(s, sizeof(s), "buffer overflow when skip, over %u.", (uint32_t)_buf_len); + throw TarsDecodeException(s); + } + } + + /// 设置缓存 + void setBuffer(const char * buf, size_t len) + { + _buf = buf; + _buf_len = len; + _cur = 0; + } + + /// 设置缓存 + template + void setBuffer(const std::vector &buf) + { + _buf = buf.data(); + _buf_len = buf.size(); + _cur = 0; + } + + /** + * 判断是否已经到BUF的末尾 + */ + bool hasEnd() + { + if(_cur > _buf_len) + { + char s[64]; + snprintf(s, sizeof(s), "buffer overflow when skip, over %u.", (uint32_t)_buf_len); + throw TarsDecodeException(s); + } + return _cur >= _buf_len; + } + size_t tellp() const + { + return _cur; + } + const char* base() const + { + return _buf; + } + size_t size() const + { + return _buf_len; + } +}; //当tars文件中含有指针型类型的数据用MapBufferReader读取 //在读数据时利用MapBufferReader提前分配的内存 减少运行过程中频繁内存分配 @@ -649,1320 +655,1320 @@ namespace tars //byte *m; //指针类型使用时需要MapBufferReader提前设定预分配内存块setMapBuffer(), //指针需要内存时通过偏移指向预分配内存块,减少解码过程中的内存申请 - class MapBufferReader : public BufferReader - { - - public: - MapBufferReader() : _buf_m(NULL),_buf_len_m(0),_cur_m(0) {} - - void reset() { _cur_m = 0; BufferReader::reset();} - - char* cur() - { - if (tars_unlikely(_buf_m == NULL)) - { - char s[64]; - snprintf(s, sizeof(s), "MapBufferReader's buff not set,_buf = null"); - throw TarsDecodeException(s); - } - return _buf_m+_cur_m; - } - - size_t left(){return _buf_len_m-_cur_m;} - - /// 跳过len个字节 - void mapBufferSkip(size_t len) - { - if (tars_unlikely(_cur_m + len > _buf_len_m)) - { - char s[64]; - snprintf(s, sizeof(s), "MapBufferReader's buffer overflow when peekBuf, over %u.", (uint32_t)_buf_len_m); - throw TarsDecodeException(s); - } - _cur_m += len; - } - - /// 设置缓存 - void setMapBuffer(char * buf, size_t len) - { - _buf_m = buf; - _buf_len_m = len; - _cur_m = 0; - } - - /// 设置缓存 - template - void setMapBuffer(std::vector &buf) - { - _buf_m = buf.data(); - _buf_len_m = buf.size(); - _cur_m = 0; - } - public: - char * _buf_m; ///< 缓冲区 - size_t _buf_len_m; ///< 缓冲区长度 - size_t _cur_m; ///< 当前位置 - }; +class MapBufferReader : public BufferReader +{ + +public: + MapBufferReader() : _buf_m(NULL),_buf_len_m(0),_cur_m(0) {} + + void reset() { _cur_m = 0; BufferReader::reset();} + + char* cur() + { + if (tars_unlikely(_buf_m == NULL)) + { + char s[64]; + snprintf(s, sizeof(s), "MapBufferReader's buff not set,_buf = null"); + throw TarsDecodeException(s); + } + return _buf_m+_cur_m; + } + + size_t left(){return _buf_len_m-_cur_m;} + + /// 跳过len个字节 + void mapBufferSkip(size_t len) + { + if (tars_unlikely(_cur_m + len > _buf_len_m)) + { + char s[64]; + snprintf(s, sizeof(s), "MapBufferReader's buffer overflow when peekBuf, over %u.", (uint32_t)_buf_len_m); + throw TarsDecodeException(s); + } + _cur_m += len; + } + + /// 设置缓存 + void setMapBuffer(char * buf, size_t len) + { + _buf_m = buf; + _buf_len_m = len; + _cur_m = 0; + } + + /// 设置缓存 + template + void setMapBuffer(std::vector &buf) + { + _buf_m = buf.data(); + _buf_len_m = buf.size(); + _cur_m = 0; + } +public: + char * _buf_m; ///< 缓冲区 + size_t _buf_len_m; ///< 缓冲区长度 + size_t _cur_m; ///< 当前位置 +}; ////////////////////////////////////////////////////////////////// /// 缓冲区写入器封装 - class BufferWriter - { - protected: - char * _buf; - size_t _len; - size_t _buf_len; - std::function _reserve = BufferWriter::reserve; //扩展空间 - - static char* reserve(BufferWriter &os, size_t len) - { - char * p = new char[(len)]; - memcpy(p, (os)._buf, (os)._len); - delete[] (os)._buf; - return p; - } - - private: - BufferWriter(const BufferWriter & bw); - BufferWriter& operator=(const BufferWriter& buf); - - public: - BufferWriter() - : _buf(NULL) - , _len(0) - , _buf_len(0) - {} - ~BufferWriter() - { - delete[] _buf; - } - - void reset() { _len = 0;} - void writeBuf(const char * buf, size_t len) - { - TarsReserveBuf(*this, _len + len); - memcpy(_buf + _len, buf, len); - _len += len; - } - std::vector getByteBuffer() const { return std::vector(_buf, _buf + _len);} - const char * getBuffer() const { return _buf;}//{ return &_buf[0]; } - size_t getLength() const { return _len;} //{ return _buf.size(); } - void swap(std::vector& v) { v.assign(_buf, _buf + _len); } - void swap(std::string& v) { v.assign(_buf, _len); } - void swap(BufferWriter& buf) - { - std::swap(_buf, buf._buf); - std::swap(_buf_len, buf._buf_len); - std::swap(_len, buf._len); - } - }; +class BufferWriter +{ +public: + char * _buf; + size_t _len; + size_t _buf_len; + std::function _reserve = BufferWriter::reserve; //扩展空间 + + static char* reserve(BufferWriter &os, size_t len) + { + char * p = new char[(len)]; + memcpy(p, (os)._buf, (os)._len); + delete[] (os)._buf; + return p; + } + +private: + BufferWriter(const BufferWriter & bw); + BufferWriter& operator=(const BufferWriter& buf); + +public: + BufferWriter() + : _buf(NULL) + , _len(0) + , _buf_len(0) + {} + ~BufferWriter() + { + delete[] _buf; + } + + void reset() { _len = 0;} + void writeBuf(const char * buf, size_t len) + { + TarsReserveBuf(*this, _len + len); + memcpy(_buf + _len, buf, len); + _len += len; + } + std::vector getByteBuffer() const { return std::vector(_buf, _buf + _len);} + const char * getBuffer() const { return _buf;}//{ return &_buf[0]; } + size_t getLength() const { return _len;} //{ return _buf.size(); } + void swap(std::vector& v) { v.assign(_buf, _buf + _len); } + void swap(std::string& v) { v.assign(_buf, _len); } + void swap(BufferWriter& buf) + { + std::swap(_buf, buf._buf); + std::swap(_buf_len, buf._buf_len); + std::swap(_len, buf._len); + } +}; /////////////////////////////////////////////////////////////////////////////////////////////////// /// 实际buffer是std::string -/// 可以swap, 把buffer交换出来, 避免一次内存copy - class BufferWriterString - { - protected: - mutable std::string _buffer; - char * _buf; - size_t _len; - size_t _buf_len; - std::function _reserve; - - private: - //不让copy 复制 - BufferWriterString(const BufferWriterString&); - BufferWriterString& operator=(const BufferWriterString& buf); - - public: - BufferWriterString() - : _buf(NULL) - , _len(0) - , _buf_len(0) - { +/// 可以swap, 把buffer交换出来, 避免一次内存copy +class BufferWriterString +{ +protected: + mutable std::string _buffer; + char * _buf; + size_t _len; + size_t _buf_len; + std::function _reserve; + +private: + //不让copy 复制 + BufferWriterString(const BufferWriterString&); + BufferWriterString& operator=(const BufferWriterString& buf); + +public: + BufferWriterString() + : _buf(NULL) + , _len(0) + , _buf_len(0) + { #ifndef GEN_PYTHON_MASK - //内存分配器 - _reserve = [](BufferWriterString &os, size_t len) { - os._buffer.resize(len); - return (char*)os._buffer.data(); - } ; + //内存分配器 + _reserve = [](BufferWriterString &os, size_t len) { + os._buffer.resize(len); + return (char*)os._buffer.data(); + } ; #endif - } - - ~BufferWriterString() - { - } - - void reset() { _len = 0;} - - void writeBuf(const char * buf, size_t len) - { - TarsReserveBuf(*this, _len + len); - memcpy(_buf + _len, buf, len); - _len += len; - } - - const std::string &getByteBuffer() const { _buffer.resize(_len); return _buffer;} - std::string &getByteBuffer() { _buffer.resize(_len); return _buffer;} - const char * getBuffer() const { return _buf;} - size_t getLength() const { return _len;} - void swap(std::string& v) - { - _buffer.resize(_len); - v.swap(_buffer); - _buf = NULL; - _buf_len = 0; - _len = 0; - } - void swap(std::vector& v) - { - _buffer.resize(_len); - v.assign(_buffer.c_str(), _buffer.c_str() + _buffer.size()); - _buf = NULL; - _buf_len = 0; - _len = 0; - } - void swap(BufferWriterString& buf) - { - buf._buffer.swap(_buffer); - std::swap(_buf, buf._buf); - std::swap(_buf_len, buf._buf_len); - std::swap(_len, buf._len); - } - }; + } + + ~BufferWriterString() + { + } + + void reset() { _len = 0;} + + void writeBuf(const char * buf, size_t len) + { + TarsReserveBuf(*this, _len + len); + memcpy(_buf + _len, buf, len); + _len += len; + } + + const std::string &getByteBuffer() const { _buffer.resize(_len); return _buffer;} + std::string &getByteBuffer() { _buffer.resize(_len); return _buffer;} + const char * getBuffer() const { return _buf;} + size_t getLength() const { return _len;} + void swap(std::string& v) + { + _buffer.resize(_len); + v.swap(_buffer); + _buf = NULL; + _buf_len = 0; + _len = 0; + } + void swap(std::vector& v) + { + _buffer.resize(_len); + v.assign(_buffer.c_str(), _buffer.c_str() + _buffer.size()); + _buf = NULL; + _buf_len = 0; + _len = 0; + } + void swap(BufferWriterString& buf) + { + buf._buffer.swap(_buffer); + std::swap(_buf, buf._buf); + std::swap(_buf_len, buf._buf_len); + std::swap(_len, buf._len); + } +}; /// 实际buffer是std::vector -/// 可以swap, 把buffer交换出来, 避免一次内存copy - class BufferWriterVector - { - protected: - mutable std::vector _buffer; - char * _buf; - size_t _len; - size_t _buf_len; - std::function _reserve; - - private: - //不让copy 复制 - BufferWriterVector(const BufferWriterVector&); - BufferWriterVector& operator=(const BufferWriterVector& buf); - - public: - BufferWriterVector() - : _buf(NULL) - , _len(0) - , _buf_len(0) - { +/// 可以swap, 把buffer交换出来, 避免一次内存copy +class BufferWriterVector +{ +protected: + mutable std::vector _buffer; + char * _buf; + size_t _len; + size_t _buf_len; + std::function _reserve; + +private: + //不让copy 复制 + BufferWriterVector(const BufferWriterVector&); + BufferWriterVector& operator=(const BufferWriterVector& buf); + +public: + BufferWriterVector() + : _buf(NULL) + , _len(0) + , _buf_len(0) + { #ifndef GEN_PYTHON_MASK - //内存分配器 - _reserve = [](BufferWriterVector &os, size_t len) { - os._buffer.resize(len); - return os._buffer.data(); - } ; + //内存分配器 + _reserve = [](BufferWriterVector &os, size_t len) { + os._buffer.resize(len); + return os._buffer.data(); + } ; #endif - } - - ~BufferWriterVector() - { - } - - void reset() { _len = 0;} - - void writeBuf(const char * buf, size_t len) - { - TarsReserveBuf(*this, _len + len); - memcpy(_buf + _len, buf, len); - _len += len; - } - - const std::vector &getByteBuffer() const { _buffer.resize(_len); return _buffer;} - std::vector &getByteBuffer() { _buffer.resize(_len); return _buffer;} - const char * getBuffer() const { return _buf;} - size_t getLength() const { return _len;} - void swap(std::string& v) - { - _buffer.resize(_len); - v.assign(_buffer.data(), _buffer.size()); - _buf = NULL; - _buf_len = 0; - _len = 0; - } - void swap(std::vector& v) - { - _buffer.resize(_len); - v.swap(_buffer); - _buf = NULL; - _buf_len = 0; - _len = 0; - } - void swap(BufferWriterVector& buf) - { - buf._buffer.swap(_buffer); - std::swap(_buf, buf._buf); - std::swap(_buf_len, buf._buf_len); - std::swap(_len, buf._len); - } - }; + } + + ~BufferWriterVector() + { + } + + void reset() { _len = 0;} + + void writeBuf(const char * buf, size_t len) + { + TarsReserveBuf(*this, _len + len); + memcpy(_buf + _len, buf, len); + _len += len; + } + + const std::vector &getByteBuffer() const { _buffer.resize(_len); return _buffer;} + std::vector &getByteBuffer() { _buffer.resize(_len); return _buffer;} + const char * getBuffer() const { return _buf;} + size_t getLength() const { return _len;} + void swap(std::string& v) + { + _buffer.resize(_len); + v.assign(_buffer.data(), _buffer.size()); + _buf = NULL; + _buf_len = 0; + _len = 0; + } + void swap(std::vector& v) + { + _buffer.resize(_len); + v.swap(_buffer); + _buf = NULL; + _buf_len = 0; + _len = 0; + } + void swap(BufferWriterVector& buf) + { + buf._buffer.swap(_buffer); + std::swap(_buf, buf._buf); + std::swap(_buf_len, buf._buf_len); + std::swap(_len, buf._len); + } +}; ////////////////////////////////////////////////////////////////// - template - class TarsInputStream : public ReaderT - { - public: - - /// 跳到指定标签的元素前 - bool skipToTag(uint8_t tag) - { - try - { - uint8_t headType = 0, headTag = 0; - while (!ReaderT::hasEnd()) - { - size_t len = 0; - TarsPeekFromHead(*this, headType, headTag, len); - if (tag <= headTag || headType == TarsHeadeStructEnd) - return headType == TarsHeadeStructEnd?false:(tag == headTag); - TarsReadHeadSkip(*this, len); - skipField(headType); - } - } - catch (TarsDecodeException& e) - { - } - return false; - } - - /// 跳到当前结构的结束 - void skipToStructEnd() - { - uint8_t headType = 0; - do - { - readFromHeadNoTag(*this, headType); - skipField(headType); - }while (headType != TarsHeadeStructEnd); - } - - /// 跳过一个字段 - void skipField() - { - uint8_t headType = 0; - readFromHeadNoTag(*this, headType); - skipField(headType); - } - - /// 跳过一个字段,不包含头信息 - void skipField(uint8_t type) - { - switch (type) - { - case TarsHeadeChar: - TarsReadHeadSkip(*this, sizeof(Char)); - break; - case TarsHeadeShort: - TarsReadHeadSkip(*this, sizeof(Short)); - break; - case TarsHeadeInt32: - TarsReadHeadSkip(*this, sizeof(Int32)); - break; - case TarsHeadeInt64: - TarsReadHeadSkip(*this, sizeof(Int64)); - break; - case TarsHeadeFloat: - TarsReadHeadSkip(*this, sizeof(Float)); - break; - case TarsHeadeDouble: - TarsReadHeadSkip(*this, sizeof(Double)); - break; - case TarsHeadeString1: - { - size_t len = 0; - TarsReadTypeBuf(*this, len, uint8_t); - TarsReadHeadSkip(*this, len); - } - break; - case TarsHeadeString4: - { - size_t len = 0; - TarsReadTypeBuf(*this, len, uint32_t); - len = ntohl((uint32_t)len); - TarsReadHeadSkip(*this, len); - } - break; - case TarsHeadeMap: - { - Int32 size = 0; - read(size, 0); - for (Int32 i = 0; i < size * 2; ++i) - skipField(); - } - break; - case TarsHeadeList: - { - Int32 size = 0; - read(size, 0); - for (Int32 i = 0; i < size; ++i) - skipField(); - } - break; - case TarsHeadeSimpleList: - { - uint8_t headType = 0, headTag = 0; - readFromHead(*this, headType, headTag); - if (tars_unlikely(headType != TarsHeadeChar)) - { - char s[64]; - snprintf(s, sizeof(s), "skipField with invalid type, type value: %d, %d, %d.", type, headType, headTag); - throw TarsDecodeMismatch(s); - } - Int32 size = 0; - read(size, 0); - TarsReadHeadSkip(*this, size); - } - break; - case TarsHeadeStructBegin: - skipToStructEnd(); - break; - case TarsHeadeStructEnd: - case TarsHeadeZeroTag: - break; - default: - { - char s[64]; - snprintf(s, sizeof(s), "skipField with invalid type, type value:%d.", type); - throw TarsDecodeMismatch(s); - } - } - } - - /// 读取一个指定类型的数据(基本类型) - template - inline T readByType() - { - T n; - this->readBuf(&n, sizeof(n)); - return n; - } - void readUnknown(std::string & sUnkown, uint8_t tag) - { - - size_t start = ReaderT::tellp(); - size_t last = start; - try - { - uint8_t lasttag = tag; - DataHead h; - while (!ReaderT::hasEnd()) - { - size_t len = h.peekFrom(*this); - if ( h.getTag() <=lasttag) - { - break; - } - lasttag = h.getTag(); - this->skip(len); - skipField(h.getType()); - last = ReaderT::tellp(); //记录下最后一次正常到达的位置 - } - } - catch (...) // - { - throw; - } - std::string s(ReaderT::base() +start, last - start); - sUnkown = s; - return ; - - } - friend class XmlProxyCallback; - - void read(Bool& b, uint8_t tag, bool isRequire = true) - { - Char c = b; - read(c, tag, isRequire); - b = c ? true : false; - } - - void read(Char& c, uint8_t tag, bool isRequire = true) - { - uint8_t headType = 0, headTag = 0; - bool skipFlag = false; - TarsSkipToTag(skipFlag, tag, headType, headTag); - if (tars_likely(skipFlag)) - { - switch (headType) - { - case TarsHeadeZeroTag: - c = 0; - break; - case TarsHeadeChar: - TarsReadTypeBuf(*this, c, Char); - break; - default: - { - char s[64]; - snprintf(s, sizeof(s), "read 'Char' type mismatch, tag: %d, get type: %d.", tag, headType); - throw TarsDecodeMismatch(s); - } - - } - } - else if (tars_unlikely(isRequire)) - { - char s[64]; - snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d.", tag, headTag); - throw TarsDecodeRequireNotExist(s); - } - } - - void read(UInt8& n, uint8_t tag, bool isRequire = true) - { - Short i = (Short)n; - read(i,tag,isRequire); - n = (UInt8)i; - } - - void read(Short& n, uint8_t tag, bool isRequire = true) - { - uint8_t headType = 0, headTag = 0; - bool skipFlag = false; - TarsSkipToTag(skipFlag, tag, headType, headTag); - if (tars_likely(skipFlag)) - { - switch (headType) - { - case TarsHeadeZeroTag: - n = 0; - break; - case TarsHeadeChar: - TarsReadTypeBuf(*this, n, Char); - break; - case TarsHeadeShort: - TarsReadTypeBuf(*this, n, Short); - n = ntohs(n); - break; - default: - { - char s[64]; - snprintf(s, sizeof(s), "read 'Short' type mismatch, tag: %d, get type: %d.", tag, headType); - throw TarsDecodeMismatch(s); - } - } - } - else if (tars_unlikely(isRequire)) - { - char s[64]; - snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); - throw TarsDecodeRequireNotExist(s); - } - } - - void read(UInt16& n, uint8_t tag, bool isRequire = true) - { - Int32 i = (Int32)n; - read(i,tag,isRequire); - n = (UInt16)i; - } - - void read(Int32& n, uint8_t tag, bool isRequire = true) - { - uint8_t headType = 1, headTag = 1; - bool skipFlag = false; - TarsSkipToTag(skipFlag, tag, headType, headTag); - if (tars_likely(skipFlag)) - { - switch (headType) - { - case TarsHeadeZeroTag: - n = 0; - break; - case TarsHeadeChar: - TarsReadTypeBuf(*this, n, Char); - break; - case TarsHeadeShort: - TarsReadTypeBuf(*this, n, Short); - n = (Short)ntohs(n); - break; - case TarsHeadeInt32: - TarsReadTypeBuf(*this, n, Int32); - n = ntohl(n); - break; - default: - { - char s[64]; - snprintf(s, sizeof(s), "read 'Int32' type mismatch, tag: %d, get type: %d.", tag, headType); - throw TarsDecodeMismatch(s); - } - } - } - else if (tars_unlikely(isRequire)) - { - char s[64]; - snprintf(s, sizeof(s), "require field not exist, tag: %d headType: %d, headTag: %d", tag, headType, headTag); - throw TarsDecodeRequireNotExist(s); - } - } - - void read(UInt32& n, uint8_t tag, bool isRequire = true) - { - Int64 i = (Int64)n; - read(i,tag,isRequire); - n = (UInt32)i; - } - - void read(Int64& n, uint8_t tag, bool isRequire = true) - { - uint8_t headType = 0, headTag = 0; - bool skipFlag = false; - TarsSkipToTag(skipFlag, tag, headType, headTag); - if (tars_likely(skipFlag)) - { - switch(headType) - { - case TarsHeadeZeroTag: - n = 0; - break; - case TarsHeadeChar: - TarsReadTypeBuf(*this, n, Char); - break; - case TarsHeadeShort: - TarsReadTypeBuf(*this, n, Short); - n = (Short) ntohs(n); - break; - case TarsHeadeInt32: - TarsReadTypeBuf(*this, n, Int32); - n = (Int32) ntohl(n); - break; - case TarsHeadeInt64: - TarsReadTypeBuf(*this, n, Int64); - n = tars_ntohll(n); - break; - default: - { - char s[64]; - snprintf(s, sizeof(s), "read 'Int64' type mismatch, tag: %d, get type: %d.", tag, headType); - throw TarsDecodeMismatch(s); - } - - } - } - else if (tars_unlikely(isRequire)) - { - char s[64]; - snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); - throw TarsDecodeRequireNotExist(s); - } - } - - void read(Float& n, uint8_t tag, bool isRequire = true) - { - uint8_t headType = 0, headTag = 0; - bool skipFlag = false; - TarsSkipToTag(skipFlag, tag, headType, headTag); - if (tars_likely(skipFlag)) - { - switch(headType) - { - case TarsHeadeZeroTag: - n = 0; - break; - case TarsHeadeFloat: - TarsReadTypeBuf(*this, n, float); - n = tars_ntohf(n); - break; - default: - { - char s[64]; - snprintf(s, sizeof(s), "read 'Float' type mismatch, tag: %d, get type: %d.", tag, headType); - throw TarsDecodeMismatch(s); - } - } - } - else if (tars_unlikely(isRequire)) - { - char s[64]; - snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); - throw TarsDecodeRequireNotExist(s); - } - } - - void read(Double& n, uint8_t tag, bool isRequire = true) - { - uint8_t headType = 0, headTag = 0; - bool skipFlag = false; - TarsSkipToTag(skipFlag, tag, headType, headTag); - if (tars_likely(skipFlag)) - { - switch(headType) - { - case TarsHeadeZeroTag: - n = 0; - break; - case TarsHeadeFloat: - TarsReadTypeBuf(*this, n, float); - n = tars_ntohf(n); - break; - case TarsHeadeDouble: - TarsReadTypeBuf(*this, n, double); - n = tars_ntohd(n); - break; - default: - { - char s[64]; - snprintf(s, sizeof(s), "read 'Double' type mismatch, tag: %d, get type: %d.", tag, headType); - throw TarsDecodeMismatch(s); - } - } - } - else if (tars_unlikely(isRequire)) - { - char s[64]; - snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); - throw TarsDecodeRequireNotExist(s); - } - } - - /*void read(std::string& s, uint8_t tag, bool isRequire = true) - { - uint8_t headType = 0, headTag = 0; - bool skipFlag = false; - TarsSkipToTag(skipFlag, tag, headType, headTag); - if (tars_likely(skipFlag)) - { - switch(headType) - { - case TarsHeadeString1: - { - size_t len = 0; - TarsReadTypeBuf(*this, len, uint8_t); - char ss[256]; - //s.resize(len); - //this->readBuf((void *)s.c_str(), len); - TarsReadStringBuf(*this, s, len); - //TarsReadBuf(*this, s, len); - //s.assign(ss, ss + len); - } - break; - case TarsHeadeString4: - { - uint32_t len = 0; - TarsReadTypeBuf(*this, len, uint32_t); - len = ntohl(len); - if (tars_unlikely(len > TARS_MAX_STRING_LENGTH)) - { - char s[128]; - snprintf(s, sizeof(s), "invalid string size, tag: %d, size: %d", tag, len); - throw TarsDecodeInvalidValue(s); - } - //char *ss = new char[len]; - //s.resize(len); - //this->readBuf((void *)s.c_str(), len); - - char *ss = new char[len]; - try - { - TarsReadBuf(*this, ss, len); - s.assign(ss, ss + len); - } - catch (...) - { - delete[] ss; - throw; - } - delete[] ss; - TarsReadStringBuf(*this, s, len); - } - break; - default: - { - char s[64]; - snprintf(s, sizeof(s), "read 'string' type mismatch, tag: %d, get type: %d.", tag, headType); - throw TarsDecodeMismatch(s); - } - } - } - else if (tars_unlikely(isRequire)) - { - char s[64]; - snprintf(s, sizeof(s), "require field not exist, tag: %d", tag); - throw TarsDecodeRequireNotExist(s); - } - }*/ - - void read(std::string& s, uint8_t tag, bool isRequire = true) - { - uint8_t headType = 0, headTag = 0; - bool skipFlag = false; - TarsSkipToTag(skipFlag, tag, headType, headTag); - if (tars_likely(skipFlag)) - { - uint32_t strLength = 0; - switch (headType) - { - case TarsHeadeString1: - { - TarsReadTypeBuf(*this, strLength, uint8_t); - } - break; - case TarsHeadeString4: - { - TarsReadTypeBuf(*this, strLength, uint32_t); - strLength = ntohl(strLength); - if (tars_unlikely(strLength > TARS_MAX_STRING_LENGTH)) - { - char s[128]; - snprintf(s, sizeof(s), "invalid string size, tag: %d, size: %d", tag, strLength); - throw TarsDecodeInvalidValue(s); - } - } - break; - default: - { - char s[64]; - snprintf(s, sizeof(s), "read 'string' type mismatch, tag: %d, get type: %d, tag: %d.", tag, headType, headTag); - throw TarsDecodeMismatch(s); - } - } - TarsReadStringBuf(*this, s, strLength); - } - else if (tars_unlikely(isRequire)) - { - char s[64]; - snprintf(s, sizeof(s), "require field not exist, tag: %d", tag); - throw TarsDecodeRequireNotExist(s); - } - } - - void read(char *buf, const UInt32 bufLen, UInt32 & readLen, uint8_t tag, bool isRequire = true) - { - uint8_t headType = 0, headTag = 0; - bool skipFlag = false; - TarsSkipToTag(skipFlag, tag, headType, headTag); - if (tars_likely(skipFlag)) - { - switch(headType) - { - case TarsHeadeSimpleList: - { - uint8_t hheadType, hheadTag; - readFromHead(*this, hheadType, hheadTag); - if (tars_unlikely(hheadType != TarsHeadeChar)) - { - char s[128]; - snprintf(s, sizeof(s), "type mismatch, tag: %d, type: %d, %d, %d", tag, headType, hheadType, hheadTag); - throw TarsDecodeMismatch(s); - } - UInt32 size = 0; - read(size, 0); - if (tars_unlikely(size > bufLen)) - { - char s[128]; - snprintf(s, sizeof(s), "invalid size, tag: %d, type: %d, %d, size: %d", tag, headType, hheadType, size); - throw TarsDecodeInvalidValue(s); - } - //TarsReadTypeBuf(*this, size, UInt32); - this->readBuf(buf, size); - readLen = size; - } - break; - - default: - { - char s[128]; - snprintf(s, sizeof(s), "type mismatch, tag: %d, type: %d", tag, headType); - throw TarsDecodeMismatch(s); - } - } - } - else if (tars_unlikely(isRequire)) - { - char s[128]; - snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); - throw TarsDecodeRequireNotExist(s); - } - } - - - template - void read(std::map& m, uint8_t tag, bool isRequire = true) - { - uint8_t headType = 0, headTag = 0; - bool skipFlag = false; - TarsSkipToTag(skipFlag, tag, headType, headTag); - if (tars_likely(skipFlag)) - { - switch(headType) - { - case TarsHeadeMap: - { - UInt32 size = 0; - read(size, 0); - if (tars_unlikely(size > this->size())) - { - char s[128]; - snprintf(s, sizeof(s), "invalid map, tag: %d, size: %d", tag, size); - throw TarsDecodeInvalidValue(s); - } - m.clear(); - - for (UInt32 i = 0; i < size; ++i) - { - std::pair pr; - read(pr.first, 0); - read(pr.second, 1); - m.insert(pr); - } - } - break; - default: - { - char s[64]; - snprintf(s, sizeof(s), "read 'map' type mismatch, tag: %d, get type: %d.", tag, headType); - throw TarsDecodeMismatch(s); - } - } - } - else if (tars_unlikely(isRequire)) - { - char s[64]; - snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); - throw TarsDecodeRequireNotExist(s); - } - } - - template - void read(std::vector& v, uint8_t tag, bool isRequire = true) - { - uint8_t headType = 0, headTag = 0; - bool skipFlag = false; - TarsSkipToTag(skipFlag, tag, headType, headTag); - if (tars_likely(skipFlag)) - { - switch(headType) - { - case TarsHeadeSimpleList: - { - uint8_t hheadType, hheadTag; - readFromHead(*this, hheadType, hheadTag); - if (tars_unlikely(hheadType != TarsHeadeChar)) - { - char s[128]; - snprintf(s, sizeof(s), "type mismatch, tag: %d, type: %d, %d, %d", tag, headType, hheadType, hheadTag); - throw TarsDecodeMismatch(s); - } - UInt32 size = 0; - read(size, 0); - if (tars_unlikely(size > this->size())) - { - char s[128]; - snprintf(s, sizeof(s), "invalid size, tag: %d, type: %d, %d, size: %d", tag, headType, hheadType, size); - throw TarsDecodeInvalidValue(s); - } - - this->readBuf(v, size); - } - break; - case TarsHeadeList: - { - UInt32 size = 0; - read(size, 0); - if (tars_unlikely(size > this->size())) - { - char s[128]; - snprintf(s, sizeof(s), "invalid size, tag: %d, type: %d, size: %d", tag, headType, size); - throw TarsDecodeInvalidValue(s); - } - v.reserve(size); - v.resize(size); - for (UInt32 i = 0; i < size; ++i) - read(v[i], 0); - } - break; - default: - { - char s[128]; - snprintf(s, sizeof(s), "type mismatch, tag: %d, type: %d", tag, headType); - throw TarsDecodeMismatch(s); - } - } - } - else if (tars_unlikely(isRequire)) - { - char s[128]; - snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); - throw TarsDecodeRequireNotExist(s); - } - } - - template - void read(std::vector& v, uint8_t tag, bool isRequire = true) - { - uint8_t headType = 0, headTag = 0; - bool skipFlag = false; - TarsSkipToTag(skipFlag, tag, headType, headTag); - if (tars_likely(skipFlag)) - { - switch(headType) - { - case TarsHeadeList: - { - UInt32 size = 0; - read(size, 0); - if (tars_unlikely(size > this->size())) - { - char s[128]; - snprintf(s, sizeof(s), "invalid size, tag: %d, type: %d, size: %d", tag, headType, size); - throw TarsDecodeInvalidValue(s); - } - v.reserve(size); - v.resize(size); - for (UInt32 i = 0; i < size; ++i) - read(v[i], 0); - } - break; - default: - { - char s[64]; - snprintf(s, sizeof(s), "read 'vector' type mismatch, tag: %d, get type: %d.", tag, headType); - throw TarsDecodeMismatch(s); - } - } - } - else if (tars_unlikely(isRequire)) - { - char s[64]; - snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); - throw TarsDecodeRequireNotExist(s); - } - } - - /// 读取结构数组 - template - void read(T* v, const UInt32 len, UInt32 & readLen, uint8_t tag, bool isRequire = true) - { - uint8_t headType = 0, headTag = 0; - bool skipFlag = false; - TarsSkipToTag(skipFlag, tag, headType, headTag); - if (tars_likely(skipFlag)) - { - switch(headType) - { - case TarsHeadeList: - { - UInt32 size = 0; - read(size, 0); - if (tars_unlikely(size > this->size())) - { - char s[128]; - snprintf(s, sizeof(s), "invalid size, tag: %d, type: %d, size: %d", tag, headType, size); - throw TarsDecodeInvalidValue(s); - } - for (UInt32 i = 0; i < size; ++i) - read(v[i], 0); - readLen = size; - } - break; - default: - { - char s[64]; - snprintf(s, sizeof(s), "read 'vector struct' type mismatch, tag: %d, get type: %d.", tag, headType); - throw TarsDecodeMismatch(s); - } - } - } - else if (tars_unlikely(isRequire)) - { - char s[64]; - snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); - throw TarsDecodeRequireNotExist(s); - } - } - - template - void read(T& v, uint8_t tag, bool isRequire = true, typename detail::disable_if, void ***>::type dummy = 0) - { - Int32 n = 0; - read(n, tag, isRequire); - v = (T) n; - } - - /// 读取结构 - template - void read(T& v, uint8_t tag, bool isRequire = true, typename detail::enable_if, void ***>::type dummy = 0) - { - uint8_t headType = 0, headTag = 0; - bool skipFlag = false; - TarsSkipToTag(skipFlag, tag, headType, headTag); - if (tars_likely(skipFlag)) - { - if (tars_unlikely(headType != TarsHeadeStructBegin)) - { - char s[64]; - snprintf(s, sizeof(s), "read 'struct' type mismatch, tag: %d, get type: %d.", tag, headType); - throw TarsDecodeMismatch(s); - } - v.readFrom(*this); - skipToStructEnd(); - } - else if (tars_unlikely(isRequire)) - { - char s[64]; - snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); - throw TarsDecodeRequireNotExist(s); - } - } - }; +template +class TarsInputStream : public ReaderT +{ +public: + + /// 跳到指定标签的元素前 + bool skipToTag(uint8_t tag) + { + try + { + uint8_t headType = 0, headTag = 0; + while (!ReaderT::hasEnd()) + { + size_t len = 0; + TarsPeekFromHead(*this, headType, headTag, len); + if (tag <= headTag || headType == TarsHeadeStructEnd) + return headType == TarsHeadeStructEnd?false:(tag == headTag); + TarsReadHeadSkip(*this, len); + skipField(headType); + } + } + catch (TarsDecodeException& e) + { + } + return false; + } + + /// 跳到当前结构的结束 + void skipToStructEnd() + { + uint8_t headType = 0; + do + { + readFromHeadNoTag(*this, headType); + skipField(headType); + }while (headType != TarsHeadeStructEnd); + } + + /// 跳过一个字段 + void skipField() + { + uint8_t headType = 0; + readFromHeadNoTag(*this, headType); + skipField(headType); + } + + /// 跳过一个字段,不包含头信息 + void skipField(uint8_t type) + { + switch (type) + { + case TarsHeadeChar: + TarsReadHeadSkip(*this, sizeof(Char)); + break; + case TarsHeadeShort: + TarsReadHeadSkip(*this, sizeof(Short)); + break; + case TarsHeadeInt32: + TarsReadHeadSkip(*this, sizeof(Int32)); + break; + case TarsHeadeInt64: + TarsReadHeadSkip(*this, sizeof(Int64)); + break; + case TarsHeadeFloat: + TarsReadHeadSkip(*this, sizeof(Float)); + break; + case TarsHeadeDouble: + TarsReadHeadSkip(*this, sizeof(Double)); + break; + case TarsHeadeString1: + { + size_t len = 0; + TarsReadTypeBuf(*this, len, uint8_t); + TarsReadHeadSkip(*this, len); + } + break; + case TarsHeadeString4: + { + size_t len = 0; + TarsReadTypeBuf(*this, len, uint32_t); + len = ntohl((uint32_t)len); + TarsReadHeadSkip(*this, len); + } + break; + case TarsHeadeMap: + { + UInt32 size = 0; + read(size, 0); + for (Int32 i = 0; i < size * 2; ++i) + skipField(); + } + break; + case TarsHeadeList: + { + UInt32 size = 0; + read(size, 0); + for (Int32 i = 0; i < size; ++i) + skipField(); + } + break; + case TarsHeadeSimpleList: + { + uint8_t headType = 0, headTag = 0; + readFromHead(*this, headType, headTag); + if (tars_unlikely(headType != TarsHeadeChar)) + { + char s[64]; + snprintf(s, sizeof(s), "skipField with invalid type, type value: %d, %d, %d.", type, headType, headTag); + throw TarsDecodeMismatch(s); + } + UInt32 size = 0; + read(size, 0); + TarsReadHeadSkip(*this, size); + } + break; + case TarsHeadeStructBegin: + skipToStructEnd(); + break; + case TarsHeadeStructEnd: + case TarsHeadeZeroTag: + break; + default: + { + char s[64]; + snprintf(s, sizeof(s), "skipField with invalid type, type value:%d.", type); + throw TarsDecodeMismatch(s); + } + } + } + + /// 读取一个指定类型的数据(基本类型) + template + inline T readByType() + { + T n; + this->readBuf(&n, sizeof(n)); + return n; + } + void readUnknown(std::string & sUnkown, uint8_t tag) + { + + size_t start = ReaderT::tellp(); + size_t last = start; + try + { + uint8_t lasttag = tag; + DataHead h; + while (!ReaderT::hasEnd()) + { + size_t len = h.peekFrom(*this); + if ( h.getTag() <=lasttag) + { + break; + } + lasttag = h.getTag(); + this->skip(len); + skipField(h.getType()); + last = ReaderT::tellp(); //记录下最后一次正常到达的位置 + } + } + catch (...) // + { + throw; + } + std::string s(ReaderT::base() +start, last - start); + sUnkown = s; + return ; + + } + friend class XmlProxyCallback; + + void read(Bool& b, uint8_t tag, bool isRequire = true) + { + Char c = b; + read(c, tag, isRequire); + b = c ? true : false; + } + + void read(Char& c, uint8_t tag, bool isRequire = true) + { + uint8_t headType = 0, headTag = 0; + bool skipFlag = false; + TarsSkipToTag(skipFlag, tag, headType, headTag); + if (tars_likely(skipFlag)) + { + switch (headType) + { + case TarsHeadeZeroTag: + c = 0; + break; + case TarsHeadeChar: + TarsReadTypeBuf(*this, c, Char); + break; + default: + { + char s[64]; + snprintf(s, sizeof(s), "read 'Char' type mismatch, tag: %d, get type: %d.", tag, headType); + throw TarsDecodeMismatch(s); + } + + } + } + else if (tars_unlikely(isRequire)) + { + char s[64]; + snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d.", tag, headTag); + throw TarsDecodeRequireNotExist(s); + } + } + + void read(UInt8& n, uint8_t tag, bool isRequire = true) + { + Short i = (Short)n; + read(i,tag,isRequire); + n = (UInt8)i; + } + + void read(Short& n, uint8_t tag, bool isRequire = true) + { + uint8_t headType = 0, headTag = 0; + bool skipFlag = false; + TarsSkipToTag(skipFlag, tag, headType, headTag); + if (tars_likely(skipFlag)) + { + switch (headType) + { + case TarsHeadeZeroTag: + n = 0; + break; + case TarsHeadeChar: + TarsReadTypeBuf(*this, n, Char); + break; + case TarsHeadeShort: + TarsReadTypeBuf(*this, n, Short); + n = ntohs(n); + break; + default: + { + char s[64]; + snprintf(s, sizeof(s), "read 'Short' type mismatch, tag: %d, get type: %d.", tag, headType); + throw TarsDecodeMismatch(s); + } + } + } + else if (tars_unlikely(isRequire)) + { + char s[64]; + snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); + throw TarsDecodeRequireNotExist(s); + } + } + + void read(UInt16& n, uint8_t tag, bool isRequire = true) + { + Int32 i = (Int32)n; + read(i,tag,isRequire); + n = (UInt16)i; + } + + void read(Int32& n, uint8_t tag, bool isRequire = true) + { + uint8_t headType = 1, headTag = 1; + bool skipFlag = false; + TarsSkipToTag(skipFlag, tag, headType, headTag); + if (tars_likely(skipFlag)) + { + switch (headType) + { + case TarsHeadeZeroTag: + n = 0; + break; + case TarsHeadeChar: + TarsReadTypeBuf(*this, n, Char); + break; + case TarsHeadeShort: + TarsReadTypeBuf(*this, n, Short); + n = (Short)ntohs(n); + break; + case TarsHeadeInt32: + TarsReadTypeBuf(*this, n, Int32); + n = ntohl(n); + break; + default: + { + char s[64]; + snprintf(s, sizeof(s), "read 'Int32' type mismatch, tag: %d, get type: %d.", tag, headType); + throw TarsDecodeMismatch(s); + } + } + } + else if (tars_unlikely(isRequire)) + { + char s[64]; + snprintf(s, sizeof(s), "require field not exist, tag: %d headType: %d, headTag: %d", tag, headType, headTag); + throw TarsDecodeRequireNotExist(s); + } + } + + void read(UInt32& n, uint8_t tag, bool isRequire = true) + { + Int64 i = (Int64)n; + read(i,tag,isRequire); + n = (UInt32)i; + } + + void read(Int64& n, uint8_t tag, bool isRequire = true) + { + uint8_t headType = 0, headTag = 0; + bool skipFlag = false; + TarsSkipToTag(skipFlag, tag, headType, headTag); + if (tars_likely(skipFlag)) + { + switch(headType) + { + case TarsHeadeZeroTag: + n = 0; + break; + case TarsHeadeChar: + TarsReadTypeBuf(*this, n, Char); + break; + case TarsHeadeShort: + TarsReadTypeBuf(*this, n, Short); + n = (Short) ntohs(n); + break; + case TarsHeadeInt32: + TarsReadTypeBuf(*this, n, Int32); + n = (Int32) ntohl(n); + break; + case TarsHeadeInt64: + TarsReadTypeBuf(*this, n, Int64); + n = tars_ntohll(n); + break; + default: + { + char s[64]; + snprintf(s, sizeof(s), "read 'Int64' type mismatch, tag: %d, get type: %d.", tag, headType); + throw TarsDecodeMismatch(s); + } + + } + } + else if (tars_unlikely(isRequire)) + { + char s[64]; + snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); + throw TarsDecodeRequireNotExist(s); + } + } + + void read(Float& n, uint8_t tag, bool isRequire = true) + { + uint8_t headType = 0, headTag = 0; + bool skipFlag = false; + TarsSkipToTag(skipFlag, tag, headType, headTag); + if (tars_likely(skipFlag)) + { + switch(headType) + { + case TarsHeadeZeroTag: + n = 0; + break; + case TarsHeadeFloat: + TarsReadTypeBuf(*this, n, float); + n = tars_ntohf(n); + break; + default: + { + char s[64]; + snprintf(s, sizeof(s), "read 'Float' type mismatch, tag: %d, get type: %d.", tag, headType); + throw TarsDecodeMismatch(s); + } + } + } + else if (tars_unlikely(isRequire)) + { + char s[64]; + snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); + throw TarsDecodeRequireNotExist(s); + } + } + + void read(Double& n, uint8_t tag, bool isRequire = true) + { + uint8_t headType = 0, headTag = 0; + bool skipFlag = false; + TarsSkipToTag(skipFlag, tag, headType, headTag); + if (tars_likely(skipFlag)) + { + switch(headType) + { + case TarsHeadeZeroTag: + n = 0; + break; + case TarsHeadeFloat: + TarsReadTypeBuf(*this, n, float); + n = tars_ntohf(n); + break; + case TarsHeadeDouble: + TarsReadTypeBuf(*this, n, double); + n = tars_ntohd(n); + break; + default: + { + char s[64]; + snprintf(s, sizeof(s), "read 'Double' type mismatch, tag: %d, get type: %d.", tag, headType); + throw TarsDecodeMismatch(s); + } + } + } + else if (tars_unlikely(isRequire)) + { + char s[64]; + snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); + throw TarsDecodeRequireNotExist(s); + } + } + + /*void read(std::string& s, uint8_t tag, bool isRequire = true) + { + uint8_t headType = 0, headTag = 0; + bool skipFlag = false; + TarsSkipToTag(skipFlag, tag, headType, headTag); + if (tars_likely(skipFlag)) + { + switch(headType) + { + case TarsHeadeString1: + { + size_t len = 0; + TarsReadTypeBuf(*this, len, uint8_t); + char ss[256]; + //s.resize(len); + //this->readBuf((void *)s.c_str(), len); + TarsReadStringBuf(*this, s, len); + //TarsReadBuf(*this, s, len); + //s.assign(ss, ss + len); + } + break; + case TarsHeadeString4: + { + uint32_t len = 0; + TarsReadTypeBuf(*this, len, uint32_t); + len = ntohl(len); + if (tars_unlikely(len > TARS_MAX_STRING_LENGTH)) + { + char s[128]; + snprintf(s, sizeof(s), "invalid string size, tag: %d, size: %d", tag, len); + throw TarsDecodeInvalidValue(s); + } + //char *ss = new char[len]; + //s.resize(len); + //this->readBuf((void *)s.c_str(), len); + + char *ss = new char[len]; + try + { + TarsReadBuf(*this, ss, len); + s.assign(ss, ss + len); + } + catch (...) + { + delete[] ss; + throw; + } + delete[] ss; + TarsReadStringBuf(*this, s, len); + } + break; + default: + { + char s[64]; + snprintf(s, sizeof(s), "read 'string' type mismatch, tag: %d, get type: %d.", tag, headType); + throw TarsDecodeMismatch(s); + } + } + } + else if (tars_unlikely(isRequire)) + { + char s[64]; + snprintf(s, sizeof(s), "require field not exist, tag: %d", tag); + throw TarsDecodeRequireNotExist(s); + } + }*/ + + void read(std::string& s, uint8_t tag, bool isRequire = true) + { + uint8_t headType = 0, headTag = 0; + bool skipFlag = false; + TarsSkipToTag(skipFlag, tag, headType, headTag); + if (tars_likely(skipFlag)) + { + uint32_t strLength = 0; + switch (headType) + { + case TarsHeadeString1: + { + TarsReadTypeBuf(*this, strLength, uint8_t); + } + break; + case TarsHeadeString4: + { + TarsReadTypeBuf(*this, strLength, uint32_t); + strLength = ntohl(strLength); + if (tars_unlikely(strLength > TARS_MAX_STRING_LENGTH)) + { + char s[128]; + snprintf(s, sizeof(s), "invalid string size, tag: %d, size: %d", tag, strLength); + throw TarsDecodeInvalidValue(s); + } + } + break; + default: + { + char s[64]; + snprintf(s, sizeof(s), "read 'string' type mismatch, tag: %d, get type: %d, tag: %d.", tag, headType, headTag); + throw TarsDecodeMismatch(s); + } + } + TarsReadStringBuf(*this, s, strLength); + } + else if (tars_unlikely(isRequire)) + { + char s[64]; + snprintf(s, sizeof(s), "require field not exist, tag: %d", tag); + throw TarsDecodeRequireNotExist(s); + } + } + + void read(char *buf, const UInt32 bufLen, UInt32 & readLen, uint8_t tag, bool isRequire = true) + { + uint8_t headType = 0, headTag = 0; + bool skipFlag = false; + TarsSkipToTag(skipFlag, tag, headType, headTag); + if (tars_likely(skipFlag)) + { + switch(headType) + { + case TarsHeadeSimpleList: + { + uint8_t hheadType, hheadTag; + readFromHead(*this, hheadType, hheadTag); + if (tars_unlikely(hheadType != TarsHeadeChar)) + { + char s[128]; + snprintf(s, sizeof(s), "type mismatch, tag: %d, type: %d, %d, %d", tag, headType, hheadType, hheadTag); + throw TarsDecodeMismatch(s); + } + UInt32 size = 0; + read(size, 0); + if (tars_unlikely(size > bufLen)) + { + char s[128]; + snprintf(s, sizeof(s), "invalid size, tag: %d, type: %d, %d, size: %d", tag, headType, hheadType, size); + throw TarsDecodeInvalidValue(s); + } + //TarsReadTypeBuf(*this, size, UInt32); + this->readBuf(buf, size); + readLen = size; + } + break; + + default: + { + char s[128]; + snprintf(s, sizeof(s), "type mismatch, tag: %d, type: %d", tag, headType); + throw TarsDecodeMismatch(s); + } + } + } + else if (tars_unlikely(isRequire)) + { + char s[128]; + snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); + throw TarsDecodeRequireNotExist(s); + } + } + + + template + void read(std::map& m, uint8_t tag, bool isRequire = true) + { + uint8_t headType = 0, headTag = 0; + bool skipFlag = false; + TarsSkipToTag(skipFlag, tag, headType, headTag); + if (tars_likely(skipFlag)) + { + switch(headType) + { + case TarsHeadeMap: + { + UInt32 size = 0; + read(size, 0); + if (tars_unlikely(size > this->size())) + { + char s[128]; + snprintf(s, sizeof(s), "invalid map, tag: %d, size: %d", tag, size); + throw TarsDecodeInvalidValue(s); + } + m.clear(); + + for (UInt32 i = 0; i < size; ++i) + { + std::pair pr; + read(pr.first, 0); + read(pr.second, 1); + m.insert(pr); + } + } + break; + default: + { + char s[64]; + snprintf(s, sizeof(s), "read 'map' type mismatch, tag: %d, get type: %d.", tag, headType); + throw TarsDecodeMismatch(s); + } + } + } + else if (tars_unlikely(isRequire)) + { + char s[64]; + snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); + throw TarsDecodeRequireNotExist(s); + } + } + + template + void read(std::vector& v, uint8_t tag, bool isRequire = true) + { + uint8_t headType = 0, headTag = 0; + bool skipFlag = false; + TarsSkipToTag(skipFlag, tag, headType, headTag); + if (tars_likely(skipFlag)) + { + switch(headType) + { + case TarsHeadeSimpleList: + { + uint8_t hheadType, hheadTag; + readFromHead(*this, hheadType, hheadTag); + if (tars_unlikely(hheadType != TarsHeadeChar)) + { + char s[128]; + snprintf(s, sizeof(s), "type mismatch, tag: %d, type: %d, %d, %d", tag, headType, hheadType, hheadTag); + throw TarsDecodeMismatch(s); + } + UInt32 size = 0; + read(size, 0); + if (tars_unlikely(size > this->size())) + { + char s[128]; + snprintf(s, sizeof(s), "invalid size, tag: %d, type: %d, %d, size: %d", tag, headType, hheadType, size); + throw TarsDecodeInvalidValue(s); + } + + this->readBuf(v, size); + } + break; + case TarsHeadeList: + { + UInt32 size = 0; + read(size, 0); + if (tars_unlikely(size > this->size())) + { + char s[128]; + snprintf(s, sizeof(s), "invalid size, tag: %d, type: %d, size: %d", tag, headType, size); + throw TarsDecodeInvalidValue(s); + } + v.reserve(size); + v.resize(size); + for (UInt32 i = 0; i < size; ++i) + read(v[i], 0); + } + break; + default: + { + char s[128]; + snprintf(s, sizeof(s), "type mismatch, tag: %d, type: %d", tag, headType); + throw TarsDecodeMismatch(s); + } + } + } + else if (tars_unlikely(isRequire)) + { + char s[128]; + snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); + throw TarsDecodeRequireNotExist(s); + } + } + + template + void read(std::vector& v, uint8_t tag, bool isRequire = true) + { + uint8_t headType = 0, headTag = 0; + bool skipFlag = false; + TarsSkipToTag(skipFlag, tag, headType, headTag); + if (tars_likely(skipFlag)) + { + switch(headType) + { + case TarsHeadeList: + { + UInt32 size = 0; + read(size, 0); + if (tars_unlikely(size > this->size())) + { + char s[128]; + snprintf(s, sizeof(s), "invalid size, tag: %d, type: %d, size: %d", tag, headType, size); + throw TarsDecodeInvalidValue(s); + } + v.reserve(size); + v.resize(size); + for (UInt32 i = 0; i < size; ++i) + read(v[i], 0); + } + break; + default: + { + char s[64]; + snprintf(s, sizeof(s), "read 'vector' type mismatch, tag: %d, get type: %d.", tag, headType); + throw TarsDecodeMismatch(s); + } + } + } + else if (tars_unlikely(isRequire)) + { + char s[64]; + snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); + throw TarsDecodeRequireNotExist(s); + } + } + + /// 读取结构数组 + template + void read(T* v, const UInt32 len, UInt32 & readLen, uint8_t tag, bool isRequire = true) + { + uint8_t headType = 0, headTag = 0; + bool skipFlag = false; + TarsSkipToTag(skipFlag, tag, headType, headTag); + if (tars_likely(skipFlag)) + { + switch(headType) + { + case TarsHeadeList: + { + UInt32 size = 0; + read(size, 0); + if (tars_unlikely(size > this->size())) + { + char s[128]; + snprintf(s, sizeof(s), "invalid size, tag: %d, type: %d, size: %d", tag, headType, size); + throw TarsDecodeInvalidValue(s); + } + for (UInt32 i = 0; i < size; ++i) + read(v[i], 0); + readLen = size; + } + break; + default: + { + char s[64]; + snprintf(s, sizeof(s), "read 'vector struct' type mismatch, tag: %d, get type: %d.", tag, headType); + throw TarsDecodeMismatch(s); + } + } + } + else if (tars_unlikely(isRequire)) + { + char s[64]; + snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); + throw TarsDecodeRequireNotExist(s); + } + } + + template + void read(T& v, uint8_t tag, bool isRequire = true, typename detail::disable_if, void ***>::type dummy = 0) + { + Int32 n = 0; + read(n, tag, isRequire); + v = (T) n; + } + + /// 读取结构 + template + void read(T& v, uint8_t tag, bool isRequire = true, typename detail::enable_if, void ***>::type dummy = 0) + { + uint8_t headType = 0, headTag = 0; + bool skipFlag = false; + TarsSkipToTag(skipFlag, tag, headType, headTag); + if (tars_likely(skipFlag)) + { + if (tars_unlikely(headType != TarsHeadeStructBegin)) + { + char s[64]; + snprintf(s, sizeof(s), "read 'struct' type mismatch, tag: %d, get type: %d.", tag, headType); + throw TarsDecodeMismatch(s); + } + v.readFrom(*this); + skipToStructEnd(); + } + else if (tars_unlikely(isRequire)) + { + char s[64]; + snprintf(s, sizeof(s), "require field not exist, tag: %d, headTag: %d", tag, headTag); + throw TarsDecodeRequireNotExist(s); + } + } +}; ////////////////////////////////////////////////////////////////// - template - class TarsOutputStream : public WriterT - { - public: - void writeUnknown(const std::string& s) - { - this->writeBuf(s.data(), s.size()); - } - void writeUnknownV2(const std::string& s) - { - DataHead::writeTo(*this, DataHead::eStructBegin, 0); - this->writeBuf(s.data(), s.size()); - DataHead::writeTo(*this, DataHead::eStructEnd, 0); - } - void write(Bool b, uint8_t tag) - { - write((Char) b, tag); - } - - void write(Char n, uint8_t tag) - { - /* - DataHead h(DataHead::eChar, tag); - if(n == 0){ - h.setType(DataHead::eZeroTag); - h.writeTo(*this); - }else{ - h.writeTo(*this); - this->writeBuf(&n, sizeof(n)); - } - */ - if (tars_unlikely(n == 0)) - { - TarsWriteToHead(*this, TarsHeadeZeroTag, tag); - } - else - { - TarsWriteToHead(*this, TarsHeadeChar, tag); - TarsWriteCharTypeBuf(*this, n, (*this)._len); - } - } - - void write(UInt8 n, uint8_t tag) - { - write((Short) n, tag); - } - - void write(Short n, uint8_t tag) - { - //if(n >= CHAR_MIN && n <= CHAR_MAX){ - if (n >= (-128) && n <= 127) - { - write((Char) n, tag); - } - else - { - /* - DataHead h(DataHead::eShort, tag); - h.writeTo(*this); - n = htons(n); - this->writeBuf(&n, sizeof(n)); - */ - TarsWriteToHead(*this, TarsHeadeShort, tag); - n = htons(n); - TarsWriteShortTypeBuf(*this, n, (*this)._len); - } - } - - void write(UInt16 n, uint8_t tag) - { - write((Int32) n, tag); - } - - void write(Int32 n, uint8_t tag) - { - //if(n >= SHRT_MIN && n <= SHRT_MAX){ - if (n >= (-32768) && n <= 32767) - { - write((Short) n, tag); - } - else - { - //DataHead h(DataHead::eInt32, tag); - //h.writeTo(*this); - TarsWriteToHead(*this, TarsHeadeInt32, tag); - n = htonl(n); - TarsWriteInt32TypeBuf(*this, n, (*this)._len); - } - } - - void write(UInt32 n, uint8_t tag) - { - write((Int64) n, tag); - } - - void write(Int64 n, uint8_t tag) - { - //if(n >= INT_MIN && n <= INT_MAX){ - if (n >= (-2147483647-1) && n <= 2147483647) - { - write((Int32) n, tag); - } - else - { - //DataHead h(DataHead::eInt64, tag); - //h.writeTo(*this); - TarsWriteToHead(*this, TarsHeadeInt64, tag); - n = tars_htonll(n); - TarsWriteInt64TypeBuf(*this, n, (*this)._len); - } - } - - void write(Float n, uint8_t tag) - { - //DataHead h(DataHead::eFloat, tag); - //h.writeTo(*this); - TarsWriteToHead(*this, TarsHeadeFloat, tag); - n = tars_htonf(n); - TarsWriteFloatTypeBuf(*this, n, (*this)._len); - } - - void write(Double n, uint8_t tag) - { - //DataHead h(DataHead::eDouble, tag); - //h.writeTo(*this); - TarsWriteToHead(*this, TarsHeadeDouble, tag); - n = tars_htond(n); - TarsWriteDoubleTypeBuf(*this, n, (*this)._len); - } - - void write(const std::string& s, uint8_t tag) - { - if (tars_unlikely(s.size() > 255)) - { - if (tars_unlikely(s.size() > TARS_MAX_STRING_LENGTH)) - { - char ss[128]; - snprintf(ss, sizeof(ss), "invalid string size, tag: %d, size: %u", tag, (uint32_t)s.size()); - throw TarsDecodeInvalidValue(ss); - } - TarsWriteToHead(*this, TarsHeadeString4, tag); - uint32_t n = htonl((uint32_t)s.size()); - TarsWriteUInt32TTypeBuf(*this, n, (*this)._len); - //this->writeBuf(s.data(), s.size()); - TarsWriteTypeBuf(*this, s.data(), s.size()); - } - else - { - TarsWriteToHead(*this, TarsHeadeString1, tag); - uint8_t n = (uint8_t)s.size(); - TarsWriteUInt8TTypeBuf(*this, n, (*this)._len); - //this->writeBuf(s.data(), s.size()); - TarsWriteTypeBuf(*this, s.data(), s.size()); - } - } - - void write(const char *buf, const UInt32 len, uint8_t tag) - { - TarsWriteToHead(*this, TarsHeadeSimpleList, tag); - TarsWriteToHead(*this, TarsHeadeChar, 0); - write(len, 0); - //this->writeBuf(buf, len); - TarsWriteTypeBuf(*this, buf, len); - } - - template - void write(const std::map& m, uint8_t tag) - { - //DataHead h(DataHead::eMap, tag); - //h.writeTo(*this); - TarsWriteToHead(*this, TarsHeadeMap, tag); - Int32 n = (Int32)m.size(); - write(n, 0); - typedef typename std::map::const_iterator IT; - for (IT i = m.begin(); i != m.end(); ++i) - { - write(i->first, 0); - write(i->second, 1); - } - } - - template - void write(const std::vector& v, uint8_t tag) - { - //DataHead h(DataHead::eList, tag); - //h.writeTo(*this); - TarsWriteToHead(*this, TarsHeadeList, tag); - Int32 n = (Int32)v.size(); - write(n, 0); - typedef typename std::vector::const_iterator IT; - for (IT i = v.begin(); i != v.end(); ++i) - write(*i, 0); - } - - template - void write(const T *v, const UInt32 len, uint8_t tag) - { - TarsWriteToHead(*this, TarsHeadeList, tag); - write(len, 0); - for (Int32 i = 0; i < (Int32)len; ++i) - { - write(v[i], 0); - } - } - - template - void write(const std::vector& v, uint8_t tag) - { - //DataHead h(DataHead::eSimpleList, tag); - //h.writeTo(*this); - //DataHead hh(DataHead::eChar, 0); - //hh.writeTo(*this); - TarsWriteToHead(*this, TarsHeadeSimpleList, tag); - TarsWriteToHead(*this, TarsHeadeChar, 0); - Int32 n = (Int32)v.size(); - write(n, 0); - //writeBuf(&v[0], v.size()); - TarsWriteTypeBuf(*this, v.data(), v.size()); - } - - template - void write(const T& v, uint8_t tag, typename detail::disable_if, void ***>::type dummy = 0) - { - write((Int32) v, tag); - } - - template - void write(const T& v, uint8_t tag, typename detail::enable_if, void ***>::type dummy = 0) - { - //DataHead h(DataHead::eStructBegin, tag); - //h.writeTo(*this); - TarsWriteToHead(*this, TarsHeadeStructBegin, tag); - v.writeTo(*this); - TarsWriteToHead(*this, TarsHeadeStructEnd, 0); - /* - h.setType(DataHead::eStructEnd); - h.setTag(0); - h.writeTo(*this); - */ - } - }; +template +class TarsOutputStream : public WriterT +{ +public: + void writeUnknown(const std::string& s) + { + this->writeBuf(s.data(), s.size()); + } + void writeUnknownV2(const std::string& s) + { + DataHead::writeTo(*this, DataHead::eStructBegin, 0); + this->writeBuf(s.data(), s.size()); + DataHead::writeTo(*this, DataHead::eStructEnd, 0); + } + void write(Bool b, uint8_t tag) + { + write((Char) b, tag); + } + + void write(Char n, uint8_t tag) + { + /* + DataHead h(DataHead::eChar, tag); + if(n == 0){ + h.setType(DataHead::eZeroTag); + h.writeTo(*this); + }else{ + h.writeTo(*this); + this->writeBuf(&n, sizeof(n)); + } + */ + if (tars_unlikely(n == 0)) + { + TarsWriteToHead(*this, TarsHeadeZeroTag, tag); + } + else + { + TarsWriteToHead(*this, TarsHeadeChar, tag); + TarsWriteCharTypeBuf(*this, n, (*this)._len); + } + } + + void write(UInt8 n, uint8_t tag) + { + write((Short) n, tag); + } + + void write(Short n, uint8_t tag) + { + //if(n >= CHAR_MIN && n <= CHAR_MAX){ + if (n >= (-128) && n <= 127) + { + write((Char) n, tag); + } + else + { + /* + DataHead h(DataHead::eShort, tag); + h.writeTo(*this); + n = htons(n); + this->writeBuf(&n, sizeof(n)); + */ + TarsWriteToHead(*this, TarsHeadeShort, tag); + n = htons(n); + TarsWriteShortTypeBuf(*this, n, (*this)._len); + } + } + + void write(UInt16 n, uint8_t tag) + { + write((Int32) n, tag); + } + + void write(Int32 n, uint8_t tag) + { + //if(n >= SHRT_MIN && n <= SHRT_MAX){ + if (n >= (-32768) && n <= 32767) + { + write((Short) n, tag); + } + else + { + //DataHead h(DataHead::eInt32, tag); + //h.writeTo(*this); + TarsWriteToHead(*this, TarsHeadeInt32, tag); + n = htonl(n); + TarsWriteInt32TypeBuf(*this, n, (*this)._len); + } + } + + void write(UInt32 n, uint8_t tag) + { + write((Int64) n, tag); + } + + void write(Int64 n, uint8_t tag) + { + //if(n >= INT_MIN && n <= INT_MAX){ + if (n >= (-2147483647-1) && n <= 2147483647) + { + write((Int32) n, tag); + } + else + { + //DataHead h(DataHead::eInt64, tag); + //h.writeTo(*this); + TarsWriteToHead(*this, TarsHeadeInt64, tag); + n = tars_htonll(n); + TarsWriteInt64TypeBuf(*this, n, (*this)._len); + } + } + + void write(Float n, uint8_t tag) + { + //DataHead h(DataHead::eFloat, tag); + //h.writeTo(*this); + TarsWriteToHead(*this, TarsHeadeFloat, tag); + n = tars_htonf(n); + TarsWriteFloatTypeBuf(*this, n, (*this)._len); + } + + void write(Double n, uint8_t tag) + { + //DataHead h(DataHead::eDouble, tag); + //h.writeTo(*this); + TarsWriteToHead(*this, TarsHeadeDouble, tag); + n = tars_htond(n); + TarsWriteDoubleTypeBuf(*this, n, (*this)._len); + } + + void write(const std::string& s, uint8_t tag) + { + if (tars_unlikely(s.size() > 255)) + { + if (tars_unlikely(s.size() > TARS_MAX_STRING_LENGTH)) + { + char ss[128]; + snprintf(ss, sizeof(ss), "invalid string size, tag: %d, size: %u", tag, (uint32_t)s.size()); + throw TarsDecodeInvalidValue(ss); + } + TarsWriteToHead(*this, TarsHeadeString4, tag); + uint32_t n = htonl((uint32_t)s.size()); + TarsWriteUInt32TTypeBuf(*this, n, (*this)._len); + //this->writeBuf(s.data(), s.size()); + TarsWriteTypeBuf(*this, s.data(), s.size()); + } + else + { + TarsWriteToHead(*this, TarsHeadeString1, tag); + uint8_t n = (uint8_t)s.size(); + TarsWriteUInt8TTypeBuf(*this, n, (*this)._len); + //this->writeBuf(s.data(), s.size()); + TarsWriteTypeBuf(*this, s.data(), s.size()); + } + } + + void write(const char *buf, const UInt32 len, uint8_t tag) + { + TarsWriteToHead(*this, TarsHeadeSimpleList, tag); + TarsWriteToHead(*this, TarsHeadeChar, 0); + write(len, 0); + //this->writeBuf(buf, len); + TarsWriteTypeBuf(*this, buf, len); + } + + template + void write(const std::map& m, uint8_t tag) + { + //DataHead h(DataHead::eMap, tag); + //h.writeTo(*this); + TarsWriteToHead(*this, TarsHeadeMap, tag); + Int32 n = (Int32)m.size(); + write(n, 0); + typedef typename std::map::const_iterator IT; + for (IT i = m.begin(); i != m.end(); ++i) + { + write(i->first, 0); + write(i->second, 1); + } + } + + template + void write(const std::vector& v, uint8_t tag) + { + //DataHead h(DataHead::eList, tag); + //h.writeTo(*this); + TarsWriteToHead(*this, TarsHeadeList, tag); + Int32 n = (Int32)v.size(); + write(n, 0); + typedef typename std::vector::const_iterator IT; + for (IT i = v.begin(); i != v.end(); ++i) + write(*i, 0); + } + + template + void write(const T *v, const UInt32 len, uint8_t tag) + { + TarsWriteToHead(*this, TarsHeadeList, tag); + write(len, 0); + for (Int32 i = 0; i < (Int32)len; ++i) + { + write(v[i], 0); + } + } + + template + void write(const std::vector& v, uint8_t tag) + { + //DataHead h(DataHead::eSimpleList, tag); + //h.writeTo(*this); + //DataHead hh(DataHead::eChar, 0); + //hh.writeTo(*this); + TarsWriteToHead(*this, TarsHeadeSimpleList, tag); + TarsWriteToHead(*this, TarsHeadeChar, 0); + Int32 n = (Int32)v.size(); + write(n, 0); + //writeBuf(&v[0], v.size()); + TarsWriteTypeBuf(*this, v.data(), v.size()); + } + + template + void write(const T& v, uint8_t tag, typename detail::disable_if, void ***>::type dummy = 0) + { + write((Int32) v, tag); + } + + template + void write(const T& v, uint8_t tag, typename detail::enable_if, void ***>::type dummy = 0) + { + //DataHead h(DataHead::eStructBegin, tag); + //h.writeTo(*this); + TarsWriteToHead(*this, TarsHeadeStructBegin, tag); + v.writeTo(*this); + TarsWriteToHead(*this, TarsHeadeStructEnd, 0); + /* + h.setType(DataHead::eStructEnd); + h.setTag(0); + h.writeTo(*this); + */ + } +}; //////////////////////////////////////////////////////////////////////////////////////////////////// } //支持iphone #ifdef __APPLE__ - #include "TarsDisplayer.h" +#include "TarsDisplayer.h" #else - #include "tup/TarsDisplayer.h" +#include "tup/TarsDisplayer.h" #endif -#endif +#endif \ No newline at end of file diff --git a/servant/tup/TarsJson.h b/servant/tup/TarsJson.h index 9304faed90bed5f50c0101d896d21d73f968e285..474ed4188b2e7520bf44a0067d0000614a26825a 100644 --- a/servant/tup/TarsJson.h +++ b/servant/tup/TarsJson.h @@ -8,7 +8,7 @@ #include #include #include - +#include "tup/TarsType.h" #include "util/tc_json.h" #include "util/tc_common.h" @@ -17,7 +17,7 @@ namespace tars class JsonInput { public: - static void readJson(Bool& b, const JsonValuePtr & p, bool isRequire = true) + static void readJson(tars::Bool& b, const JsonValuePtr & p, bool isRequire = true) { if(NULL != p.get() && p->getType() == eJsonTypeBoolean) { @@ -26,7 +26,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'Bool' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'Bool' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -40,7 +40,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'Char' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'Char' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -54,7 +54,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'Uint8' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'Uint8' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -68,7 +68,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'Short' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'Short' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -82,7 +82,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'Uint16' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'Uint16' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -96,7 +96,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'Int32' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'Int32' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -110,7 +110,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'UInt32' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'UInt32' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -124,7 +124,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'Int64' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'Int64' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -138,7 +138,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'Float' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'Float' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -152,7 +152,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'Double' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'Double' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -166,7 +166,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'string' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'string' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -188,7 +188,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'char *' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'char *' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -212,7 +212,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -235,7 +235,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -258,7 +258,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -280,7 +280,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -302,7 +302,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -325,7 +325,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -348,7 +348,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -371,7 +371,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -394,7 +394,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -417,7 +417,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -440,7 +440,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -468,7 +468,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'vector' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'vector' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -495,7 +495,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'T *' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'T *' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } @@ -520,7 +520,7 @@ public: else if (isRequire) { char s[128]; - snprintf(s, sizeof(s), "read 'Char' type mismatch, get type: %d.", p->getType()); + snprintf(s, sizeof(s), "read 'Char' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); throw TC_Json_Exception(s); } } diff --git a/servant/tup/TarsType.h b/servant/tup/TarsType.h index 26738f6a67a74440f9039ea2c700b4d234036066..cd2d696b6f733f72e5fc0b6334270476311423a5 100644 --- a/servant/tup/TarsType.h +++ b/servant/tup/TarsType.h @@ -1,4 +1,4 @@ -/** +/** * Tencent is pleased to support the open source community by making Tars available. * * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. @@ -43,12 +43,13 @@ typedef short Short; typedef float Float; typedef double Double; typedef int Int32; +struct TarsStructBase; typedef unsigned char UInt8; typedef unsigned short UInt16; typedef unsigned int UInt32; -#if __WORDSIZE == 64 || defined _WIN64 +#if __WORDSIZE == 64 typedef long Int64; #else typedef long long Int64; @@ -72,7 +73,7 @@ typedef long long Int64; | (((x) & 0x000000000000ff00ull) << 40) \ | (((x) & 0x00000000000000ffull) << 56)) */ -#ifdef __APPLE__ +#if (defined(__APPLE__) || defined(_WIN32)) # ifndef __LITTLE_ENDIAN # define __LITTLE_ENDIAN 1234 # endif diff --git a/servant/tup/TarsXml.h b/servant/tup/TarsXml.h new file mode 100755 index 0000000000000000000000000000000000000000..5574e26989f7e73e4570fd32f52e24bb37c24a51 --- /dev/null +++ b/servant/tup/TarsXml.h @@ -0,0 +1,780 @@ +#ifndef __TARS_XML_H__ +#define __TARS_XML_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util/tc_xml.h" +#include "util/tc_common.h" + +namespace tars +{ +class XmlInput +{ +public: + static void readXml(Bool& b, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeString) + { + b = TC_Common::lower(XmlValueStringPtr::dynamicCast(p)->value) == "true"; + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'Bool' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + static void readXml(Char& c, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeString) + { + c = TC_Common::strto(XmlValueStringPtr::dynamicCast(p)->value); + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'Char' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + static void readXml(UInt8& n, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeString) + { + n = TC_Common::strto(XmlValueStringPtr::dynamicCast(p)->value); + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'Uint8' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + static void readXml(Short& n, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeString) + { + n = TC_Common::strto(XmlValueStringPtr::dynamicCast(p)->value); + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'Short' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + static void readXml(UInt16& n, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeString) + { + n = TC_Common::strto(XmlValueStringPtr::dynamicCast(p)->value); + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'Uint16' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + static void readXml(Int32& n, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeString) + { + n = TC_Common::strto(XmlValueStringPtr::dynamicCast(p)->value); + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'Int32' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + static void readXml(UInt32& n, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeString) + { + n = TC_Common::strto(XmlValueStringPtr::dynamicCast(p)->value); + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'UInt32' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + static void readXml(Int64& n, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeString) + { + n = TC_Common::strto(XmlValueStringPtr::dynamicCast(p)->value); + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'Int64' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + static void readXml(Float& n, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeString) + { + n = TC_Common::strto(XmlValueStringPtr::dynamicCast(p)->value); + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'Float' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + static void readXml(Double& n, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeString) + { + n = TC_Common::strto(XmlValueStringPtr::dynamicCast(p)->value); + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'Double' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + static void readXml(std::string& s, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeString) + { + s = XmlValueStringPtr::dynamicCast(p)->value; + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'string' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + static void readXml(char *buf, const UInt32 bufLen, UInt32 & readLen, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeString) + { + XmlValueStringPtr pString=XmlValueStringPtr::dynamicCast(p); + if((UInt32)pString->value.size()>bufLen) + { + char s[128]; + snprintf(s, sizeof(s), "invalid char * size, size: %u", (UInt32)pString->value.size()); + throw TC_Xml_Exception(s); + } + memcpy(buf,pString->value.c_str(),pString->value.size()); + readLen = pString->value.size(); + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'char *' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + + template + static void readXml(std::map& m, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeObj) + { + XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p); + map::iterator iter; + iter=pObj->value.begin(); + for(;iter!=pObj->value.end();++iter) + { + std::pair pr; + pr.first=iter->first; + readXml(pr.second,iter->second); + m.insert(pr); + } + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + template + static void readXml(std::map& m, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeObj) + { + XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p); + map::iterator iter; + iter=pObj->value.begin(); + for(;iter!=pObj->value.end();++iter) + { + std::pair pr; + pr.first=TC_Common::strto(iter->first); + readXml(pr.second,iter->second); + m.insert(pr); + } + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + template + static void readXml(std::map& m, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeObj) + { + XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p); + map::iterator iter; + iter=pObj->value.begin(); + for(;iter!=pObj->value.end();++iter) + { + std::pair pr; + pr.first=TC_Common::strto(iter->first); + readXml(pr.second,iter->second); + m.insert(pr); + } + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + template + static void readXml(std::map& m, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeObj) + { + XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p); + map::iterator iter; + iter=pObj->value.begin(); + for(;iter!=pObj->value.end();++iter) + { + std::pair pr; + pr.first=TC_Common::strto(iter->first); + readXml(pr.second,iter->second); + m.insert(pr); + } + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + template + static void readXml(std::map& m, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeObj) + { + XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p); + map::iterator iter; + iter=pObj->value.begin(); + for(;iter!=pObj->value.end();++iter) + { + std::pair pr; + pr.first=TC_Common::strto(iter->first); + readXml(pr.second,iter->second); + m.insert(pr); + } + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + template + static void readXml(std::map& m, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeObj) + { + XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p); + map::iterator iter; + iter=pObj->value.begin(); + for(;iter!=pObj->value.end();++iter) + { + std::pair pr; + pr.first=TC_Common::strto(iter->first); + readXml(pr.second,iter->second); + m.insert(pr); + } + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + template + static void readXml(std::map& m, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeObj) + { + XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p); + map::iterator iter; + iter=pObj->value.begin(); + for(;iter!=pObj->value.end();++iter) + { + std::pair pr; + pr.first=TC_Common::strto(iter->first); + readXml(pr.second,iter->second); + m.insert(pr); + } + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + template + static void readXml(std::map& m, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeObj) + { + XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p); + map::iterator iter; + iter=pObj->value.begin(); + for(;iter!=pObj->value.end();++iter) + { + std::pair pr; + pr.first=TC_Common::strto(iter->first); + readXml(pr.second,iter->second); + m.insert(pr); + } + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + template + static void readXml(std::map& m, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeObj) + { + XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p); + map::iterator iter; + iter=pObj->value.begin(); + for(;iter!=pObj->value.end();++iter) + { + std::pair pr; + pr.first=TC_Common::strto(iter->first); + readXml(pr.second,iter->second); + m.insert(pr); + } + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + template + static void readXml(std::map& m, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeObj) + { + XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p); + map::iterator iter; + iter=pObj->value.begin(); + for(;iter!=pObj->value.end();++iter) + { + std::pair pr; + pr.first=TC_Common::strto(iter->first); + readXml(pr.second,iter->second); + m.insert(pr); + } + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + template + static void readXml(std::map& m, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeObj) + { + XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p); + map::iterator iter; + iter=pObj->value.begin(); + for(;iter!=pObj->value.end();++iter) + { + std::pair pr; + pr.first=TC_Common::strto(iter->first); + readXml(pr.second,iter->second); + m.insert(pr); + } + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + template + static void readXml(std::map& m, const XmlValuePtr & p, bool isRequire = true) + { + char s[128]; + snprintf(s, sizeof(s), "map key is not Basic type. map key is only string|bool|num"); + throw TC_Xml_Exception(s); + } + + template + static void readXml(std::vector& v, const XmlValuePtr & p, bool isRequire = true) + { + if (NULL != p.get() && p->getType() == eXmlTypeArray) + { + XmlValueArrayPtr pArray=XmlValueArrayPtr::dynamicCast(p); + v.resize(pArray->value.size()); + for(size_t i=0;ivalue.size();++i) + { + readXml(v[i],pArray->value[i]); + } + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'vector' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + /// 读取结构数组 + template + static void readXml(T* v, const UInt32 len, UInt32 & readLen, const XmlValuePtr & p, bool isRequire = true) + { + if(NULL != p.get() && p->getType() == eXmlTypeArray) + { + XmlValueArrayPtr pArray=XmlValueArrayPtr::dynamicCast(p); + if(pArray->value.size()>len) + { + char s[128]; + snprintf(s, sizeof(s), "read 'T *' invalid size, size: %u", (uint32_t)pArray->value.size()); + throw TC_Xml_Exception(s); + } + for(size_t i=0;ivalue.size();++i) + { + readXml(v[i],pArray->value[i]); + } + readLen=pArray->value.size(); + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'T *' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } + + template + static void readXml(T& v, const XmlValuePtr & p, bool isRequire = true, typename detail::disable_if, void ***>::type dummy = 0) + { + Int32 n = 0; + readXml(n, p, isRequire); + v = (T) n; + } + + /// 读取结构 + template + static void readXml(T& v, const XmlValuePtr & p, bool isRequire = true, typename detail::enable_if, void ***>::type dummy = 0) + { + if(NULL != p.get() && p->getType() == eXmlTypeObj) + { + XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p); + v.readFromXml(pObj); + } + else if (isRequire) + { + char s[128]; + snprintf(s, sizeof(s), "read 'Char' type mismatch, get type: %d.", (p.get() ? p->getType() : 0)); + throw TC_Xml_Exception(s); + } + } +}; + +class XmlOutput +{ +public: + static XmlValueStringPtr writeXml(Bool b, bool cdata = false) + { + return (new XmlValueString(b ? "true" : "false", cdata)); + } + + static XmlValueStringPtr writeXml(Char n, bool cdata = false) + { + return (new XmlValueString(TC_Common::tostr(n), cdata)); + } + + static XmlValueStringPtr writeXml(UInt8 n, bool cdata = false) + { + return (new XmlValueString(TC_Common::tostr(n), cdata)); + } + + static XmlValueStringPtr writeXml(Short n, bool cdata = false) + { + return (new XmlValueString(TC_Common::tostr(n), cdata)); + } + + static XmlValueStringPtr writeXml(UInt16 n, bool cdata = false) + { + return (new XmlValueString(TC_Common::tostr(n), cdata)); + } + + static XmlValueStringPtr writeXml(Int32 n, bool cdata = false) + { + return (new XmlValueString(TC_Common::tostr(n), cdata)); + } + + static XmlValueStringPtr writeXml(UInt32 n, bool cdata = false) + { + return (new XmlValueString(TC_Common::tostr(n), cdata)); + } + + static XmlValueStringPtr writeXml(Int64 n, bool cdata = false) + { + return (new XmlValueString(TC_Common::tostr(n), cdata)); + } + + static XmlValueStringPtr writeXml(Float n, bool cdata = false) + { + return (new XmlValueString(TC_Common::tostr(n), cdata)); + } + + static XmlValueStringPtr writeXml(Double n, bool cdata = false) + { + return (new XmlValueString(TC_Common::tostr(n), cdata)); + } + + static XmlValueStringPtr writeXml(const std::string& s, bool cdata = false) + { + return (new XmlValueString(s, cdata)); + } + + static XmlValueStringPtr writeXml(const char *buf, const UInt32 len, bool cdata = false) + { + return (new XmlValueString(string(buf,len), cdata)); + } + + template + static XmlValueObjPtr writeXml(const std::map& m) + { + XmlValueObjPtr pObj=new XmlValueObj(); + typedef typename std::map::const_iterator IT; + for (IT i = m.begin(); i != m.end(); ++i) + { + pObj->value[i->first]=writeXml(i->second); + } + return pObj; + } + + template + static XmlValueObjPtr writeXml(const std::map& m) + { + XmlValueObjPtr pObj=new XmlValueObj(); + typedef typename std::map::const_iterator IT; + for (IT i = m.begin(); i != m.end(); ++i) + { + pObj->value[TC_Common::tostr(i->first)]=writeXml(i->second); + } + return pObj; + } + + template + static XmlValueObjPtr writeXml(const std::map& m) + { + XmlValueObjPtr pObj=new XmlValueObj(); + typedef typename std::map::const_iterator IT; + for (IT i = m.begin(); i != m.end(); ++i) + { + pObj->value[TC_Common::tostr((Int32)i->first)]=writeXml(i->second); + } + return pObj; + } + + template + static XmlValueObjPtr writeXml(const std::map& m) + { + XmlValueObjPtr pObj=new XmlValueObj(); + typedef typename std::map::const_iterator IT; + for (IT i = m.begin(); i != m.end(); ++i) + { + pObj->value[TC_Common::tostr(i->first)]=writeXml(i->second); + } + return pObj; + } + + template + static XmlValueObjPtr writeXml(const std::map& m) + { + XmlValueObjPtr pObj=new XmlValueObj(); + typedef typename std::map::const_iterator IT; + for (IT i = m.begin(); i != m.end(); ++i) + { + pObj->value[TC_Common::tostr(i->first)]=writeXml(i->second); + } + return pObj; + } + template + static XmlValueObjPtr writeXml(const std::map& m) + { + XmlValueObjPtr pObj=new XmlValueObj(); + typedef typename std::map::const_iterator IT; + for (IT i = m.begin(); i != m.end(); ++i) + { + pObj->value[TC_Common::tostr(i->first)]=writeXml(i->second); + } + return pObj; + } + template + static XmlValueObjPtr writeXml(const std::map& m) + { + XmlValueObjPtr pObj=new XmlValueObj(); + typedef typename std::map::const_iterator IT; + for (IT i = m.begin(); i != m.end(); ++i) + { + pObj->value[TC_Common::tostr(i->first)]=writeXml(i->second); + } + return pObj; + } + template + static XmlValueObjPtr writeXml(const std::map& m) + { + XmlValueObjPtr pObj=new XmlValueObj(); + typedef typename std::map::const_iterator IT; + for (IT i = m.begin(); i != m.end(); ++i) + { + pObj->value[TC_Common::tostr(i->first)]=writeXml(i->second); + } + return pObj; + } + + template + static XmlValueObjPtr writeXml(const std::map& m) + { + XmlValueObjPtr pObj=new XmlValueObj(); + typedef typename std::map::const_iterator IT; + for (IT i = m.begin(); i != m.end(); ++i) + { + pObj->value[TC_Common::tostr(i->first)]=writeXml(i->second); + } + return pObj; + } + + template + static XmlValueObjPtr writeXml(const std::map& m) + { + XmlValueObjPtr pObj=new XmlValueObj(); + typedef typename std::map::const_iterator IT; + for (IT i = m.begin(); i != m.end(); ++i) + { + pObj->value[TC_Common::tostr(i->first)]=writeXml(i->second); + } + return pObj; + } + + template + static XmlValueObjPtr writeXml(const std::map& m) + { + XmlValueObjPtr pObj=new XmlValueObj(); + typedef typename std::map::const_iterator IT; + for (IT i = m.begin(); i != m.end(); ++i) + { + pObj->value[TC_Common::tostr(i->first)]=writeXml(i->second); + } + return pObj; + } + + template + static XmlValueObjPtr writeXml(const std::map& m) + { + char s[128]; + snprintf(s, sizeof(s), "map key is not Basic type. map key is only string|bool|num"); + throw TC_Xml_Exception(s); + } + + template + static XmlValueArrayPtr writeXml(const std::vector& v) + { + XmlValueArrayPtr pArray=new XmlValueArray(); + typedef typename std::vector::const_iterator IT; + for (IT i = v.begin(); i != v.end(); ++i) + pArray->value.push_back(writeXml(*i)); + return pArray; + } + + template + static XmlValueArrayPtr writeXml(const T *v, const UInt32 len) + { + XmlValueArrayPtr pArray=new XmlValueArray(); + for (size_t i = 0; i < len; ++i) + { + pArray->value.push_back(writeXml(v[i])); + } + return pArray; + } + + template + static XmlValueStringPtr writeXml(const T& v, typename detail::disable_if, void ***>::type dummy = 0) + { + return writeXml((Int32) v); + } + + template + static XmlValueObjPtr writeXml(const T& v, typename detail::enable_if, void ***>::type dummy = 0) + { + return v.writeToXml(); + } +}; +//////////////////////////////////////////////////////////////////////////////////////////////////// +} + + +#endif diff --git a/test b/test new file mode 100644 index 0000000000000000000000000000000000000000..30d74d258442c7c65512eafab474568dd706c430 --- /dev/null +++ b/test @@ -0,0 +1 @@ +test \ No newline at end of file diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt old mode 100644 new mode 100755 index 013766038380b6055cc728c18c1127a4d8cf8c5b..6f996b3697fa907acf1f74aba2e8ab197a22c9fb --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -6,7 +6,12 @@ include_directories(${util_SOURCE_DIR}/include) link_libraries(tarsutil) function(tars2language TARGET) - set(EXECUTABLE_OUTPUT_PATH "${PROJECT_BINARY_DIR}/bin") + set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/bin") + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES}) + string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/bin) + endforeach() include_directories(${PROJECT_SOURCE_DIR}/tarsparse) @@ -21,81 +26,6 @@ function(tars2language TARGET) endfunction() IF(UNIX) - -macro(complice_lex OUT_DEPENDS_LEX_LIST) - set(DEPENDS_LIST) - - FILE(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/*.l") - -# set(CLEAN_LIST) - - foreach (FILE ${SRC_LIST}) - - get_filename_component(NAME_WE ${FILE} NAME_WE) - - set(LEX_IN ${FILE}) - set(LEX_CPP ${NAME_WE}.lex.cpp) - - add_custom_command( - OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${LEX_CPP} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${LEX_IN} - COMMAND flex --nounist ${LEX_IN} - COMMENT "flex --nounist ${LEX_IN}") - - list(APPEND DEPENDS_LIST ${CMAKE_CURRENT_SOURCE_DIR}/${LEX_CPP}) - - get_filename_component(PATH ${FILE} PATH) -# list(APPEND CLEAN_LIST ${PATH}/${LEX_CPP}) - - endforeach (FILE) - - set(OUT_DEPENDS_LEX_LIST ${DEPENDS_LIST}) - -# set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CLEAN_LIST}") - -endmacro() - -macro(complice_yacc OUT_DEPENDS_YACC_LIST) - set(DEPENDS_LIST) - - FILE(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/*.y") - -# set(CLEAN_LIST) - - foreach (FILE ${SRC_LIST}) - - get_filename_component(NAME_WE ${FILE} NAME_WE) - - set(YACC_IN ${FILE}) - set(YACC_H ${NAME_WE}.tab.hpp) - set(YACC_CPP ${NAME_WE}.tab.cpp) - - add_custom_command( - OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${YACC_H} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${YACC_IN} - COMMAND bison ${YACC_IN} -o ${YACC_CPP} - COMMENT "bison ${YACC_IN} -o ${YACC_CPP}") - - list(APPEND DEPENDS_LIST ${CMAKE_CURRENT_SOURCE_DIR}/${YACC_H}) - - get_filename_component(PATH ${FILE} PATH) - -# list(APPEND CLEAN_LIST ${PATH}/${YACC_H}) -# list(APPEND CLEAN_LIST ${PATH}/${YACC_CPP}) - #if (EXISTS ${PATH}/${NAME_WE}.tab.cpp) - # list(APPEND CLEAN_LIST ${PATH}/${NAME_WE}.tab.cpp) - #endif (EXISTS ${PATH}/${NAME_WE}.tab.cpp) - - endforeach (FILE) - -# set(OUT_DEPENDS_YACC_LIST ${DEPENDS_LIST}) - -# set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CLEAN_LIST}") - -endmacro() - add_subdirectory(tarsgrammar) ENDIF(UNIX) @@ -108,6 +38,7 @@ add_subdirectory(tars2oc) add_subdirectory(tars2php) add_subdirectory(tars2android) add_subdirectory(tars2node) +add_subdirectory(tars2case) IF(TARS_PROTOBUF) add_subdirectory(pb2tarscpp) diff --git a/tools/README.md b/tools/README.md old mode 100644 new mode 100755 index 8df41fde978ea63664d94d77e695c8ef3cae0ce3..7318150b8eb7ff48472ff37daa0240daa741a2ca --- a/tools/README.md +++ b/tools/README.md @@ -17,4 +17,5 @@ tars2php | Source code implementation of IDL tool for generating PHP code t tars2python | Source code implementation of IDL tool for generating Python code through tars file tars2node | Source code implementation of IDL tool for generating Node.js code through tars file tars2android | Source code implementation of IDL tool for generating Android code through tars file +tars2case | Generate test case for tars server pb2tarscpp | Generate protoc plugin source code for tars C++ code via proto file diff --git a/tools/README.zh.md b/tools/README.zh.md old mode 100644 new mode 100755 index bb2d0baec23a15134c624a4096949f27cbccf4e9..7705cec60c0bcd6b1d7b8931465ef466e6dc9b1f --- a/tools/README.zh.md +++ b/tools/README.zh.md @@ -15,4 +15,5 @@ tars2php | 通过tars文件生成 PHP 代码的IDL工具的源码实现 tars2python | 通过tars文件生成 Python 代码的IDL工具的源码实现 tars2node | 通过tars文件生成 Node.js 代码的IDL工具的源码实现 tars2android | 通过tars文件生成 Android 代码的IDL工具的源码实现 +tars2case | 通过tars文件生成 tars 服务生成测试用例 pb2tarscpp | 通过proto文件生成tars C++ 代码的protoc插件源码实现 diff --git a/tools/tars2case/CMakeLists.txt b/tools/tars2case/CMakeLists.txt new file mode 100755 index 0000000000000000000000000000000000000000..d994ea8cd5a090cdb8b7e6c959ac9162e84a516c --- /dev/null +++ b/tools/tars2case/CMakeLists.txt @@ -0,0 +1 @@ +tars2language("tars2case") diff --git a/tools/tars2case/main.cpp b/tools/tars2case/main.cpp new file mode 100755 index 0000000000000000000000000000000000000000..8f8d8caf39fcdaefbd7410248a6f00d394ef5f35 --- /dev/null +++ b/tools/tars2case/main.cpp @@ -0,0 +1,100 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT 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 "util/tc_file.h" +#include "util/tc_option.h" + +#include "tars2case.h" + +void usage() +{ + cout << "Usage : tars2case [OPTION] tarsfile" << endl; + cout << " --json generate json casefile" << endl; + cout << " --web generate webadmin casefile" << endl; + cout << " --dir=DIRECTORY generate casefile to DIRECTORY" << endl; + + cout << endl; + exit(100); +} + + +void check(vector &vTars) +{ + for(size_t i = 0; i < vTars.size(); i++) + { + string ext = TC_File::extractFileExt(vTars[i]); + if(ext == "tars") + { + if(!TC_File::isFileExist(vTars[i])) + { + cerr << "file '" << vTars[i] << "' not exists" << endl; + usage(); + } + } + else + { + cerr << "only support tars file." << endl; + exit(100); + } + } +} + + +void doTars2Test(TC_Option& option, const vector& vTars) +{ + Tars2Case j2t; + j2t.setJsonCase(option.hasParam("json") ? true : false); + j2t.setWebSupport(option.hasParam("web") ? true : false); + j2t.setBaseDir(option.getValue("dir").empty() ? "" : option.getValue("dir")); + + g_parse->setUseCurrentPath(true); + for(size_t i = 0; i < vTars.size(); i++) + { + g_parse->parse(vTars[i]); + j2t.createFile(vTars[i], option.getValue("out")); + } +} + +int main(int argc, char* argv[]){ + + if (argc < 2) + { + usage(); + return 100; + } + + try + { + TC_Option option; + option.decode(argc, argv); + vector vTars = option.getSingle(); + + check(vTars); + ::chdir(TC_File::extractFilePath(vTars[0]).c_str()); + if (option.hasParam("help")) + { + usage(); + } + doTars2Test(option, vTars); + } + catch(exception& e) + { + cerr< + +////////////////////////////////////////////////////////////////////////////////// +// +Tars2Case::Tars2Case() : _jsonCase(false), _webCase(false) +{ +} + +string Tars2Case::toDescStr(const TypePtr &pPtr) const +{ + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); + if (bPtr) + { + switch (bPtr->kind()) + { + case Builtin::KindByte: return bPtr->isUnsigned() ? "byte_u" : "byte"; break; + case Builtin::KindShort: return bPtr->isUnsigned() ? "short_u" : "short"; break; + case Builtin::KindInt: return bPtr->isUnsigned() ? "int_u" : "int"; break; + case Builtin::KindLong: return "long"; break; + case Builtin::KindBool: return "bool"; break; + case Builtin::KindFloat: return "float"; break; + case Builtin::KindDouble: return "double"; break; + case Builtin::KindString: return "string"; break; + default: assert(false); break; + } + } + + VectorPtr vPtr = VectorPtr::dynamicCast(pPtr); + if (vPtr) return "vector"; + + MapPtr mPtr = MapPtr::dynamicCast(pPtr); + if (mPtr) return "map"; + + StructPtr sPtr = StructPtr::dynamicCast(pPtr); + if (sPtr) return "struct"; + + EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); + if (ePtr) return "int"; + + return "void"; +} + + +string Tars2Case::toStr(const TypePtr &pPtr) const +{ + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); + if (bPtr) return tostrBuiltin(bPtr); + + VectorPtr vPtr = VectorPtr::dynamicCast(pPtr); + if (vPtr) return tostrVector(vPtr); + + MapPtr mPtr = MapPtr::dynamicCast(pPtr); + if (mPtr) return tostrMap(mPtr); + + StructPtr sPtr = StructPtr::dynamicCast(pPtr); + if (sPtr) return tostrStruct(sPtr); + + EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); + if (ePtr) return tostrEnum(ePtr); + + if (!pPtr) return "void"; + + assert(false); + return ""; +} + +string Tars2Case::toCase(const TypePtr &pPtr, const string& varName) const +{ + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); + if (bPtr) return tocaseBuiltin(bPtr, varName); + + VectorPtr vPtr = VectorPtr::dynamicCast(pPtr); + if (vPtr) return tocaseVector(vPtr, varName); + + MapPtr mPtr = MapPtr::dynamicCast(pPtr); + if (mPtr) return tocaseMap(mPtr, varName); + + StructPtr sPtr = StructPtr::dynamicCast(pPtr); + if (sPtr) return tocaseStruct(sPtr, varName); + + EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); + if (ePtr) return tocaseEnum(ePtr, varName); + + if (!pPtr) return "void"; + + assert(false); + return ""; +} + + +/*******************************BuiltinPtr********************************/ +string Tars2Case::tostrBuiltin(const BuiltinPtr &pPtr) const +{ + string s; + + switch (pPtr->kind()) + { + case Builtin::KindBool: + s = "bool"; + break; + case Builtin::KindByte: + s = pPtr->isUnsigned() ? "short" : "byte"; + break; + case Builtin::KindShort: + s = pPtr->isUnsigned() ? "int" : "short"; + break; + case Builtin::KindInt: + s = pPtr->isUnsigned() ? "long" : "int"; + break; + case Builtin::KindLong: + s = "long"; + break; + case Builtin::KindFloat: + s = "float"; + break; + case Builtin::KindDouble: + s = "double"; + break; + case Builtin::KindString: + s = "string"; + break; + case Builtin::KindVector: + s = "vector"; + break; + case Builtin::KindMap: + s = "map"; + break; + default: + assert(false); + break; + } + + return s; +} + +string Tars2Case::tocaseBuiltin(const BuiltinPtr &pPtr, const string& varName) const +{ + string s; + + switch (pPtr->kind()) + { + case Builtin::KindBool: + s = "true"; + break; + case Builtin::KindByte: + s = "0"; + break; + case Builtin::KindShort: + s = "0"; + break; + case Builtin::KindInt: + s = "0"; + break; + case Builtin::KindLong: + s = "0"; + break; + case Builtin::KindFloat: + s = "0.0"; + break; + case Builtin::KindDouble: + s = "0.00"; + break; + case Builtin::KindString: + s = "key"; + break; +/* + case Builtin::KindVector: + s = "vector"; + break; + case Builtin::KindMap: + s = "map"; + break; +*/ + default: + assert(false); + break; + } + + return s; +} +/*******************************VectorPtr********************************/ +string Tars2Case::tostrVector(const VectorPtr &pPtr) const +{ + string s; + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr()); + s = "vector" + string("<") + toStr(pPtr->getTypePtr()) + ">"; + return s; +} + +string Tars2Case::tocaseVector(const VectorPtr &pPtr, const string& varName) const +{ + string s; + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr()); + s = string("<"); + for(int i = 0; i < 2; i++) { + if(i != 0) { + s += ","; + } + s += toCase(pPtr->getTypePtr(), varName); + } + s += ">"; + return s; +} + +string Tars2Case::tostrMap(const MapPtr &pPtr, bool bNew) const +{ + string s = "map"; + s += string("<") + toStr(pPtr->getLeftTypePtr()) + "," + toStr(pPtr->getRightTypePtr()) + ">"; + + return s; +} + +string Tars2Case::tocaseMap(const MapPtr &pPtr, const string& varName) const +{ + string s = string("["); + for(int i = 0; i < 2; i++) { + if(i != 0) { + s += ","; + } + s += toCase(pPtr->getLeftTypePtr(), varName) + "=" + toCase(pPtr->getRightTypePtr(), varName); + } + s += "]"; + + return s; +} + + +string Tars2Case::tostrStruct(const StructPtr &pPtr) const +{ + vector& members = pPtr->getAllMemberPtr(); + string s; + + //是否生成tag和require等信息 + bool genTag = false; + for(size_t i = 0; i < members.size(); i++) { + TypeIdPtr typeId = members[i]; + if(!s.empty()) { + s += ","; + } + + if(i == 0) { + if(typeId->getTag() == 0) { + genTag = false; + } + else { + genTag = true; + } + } + else { + //检查tag是否连续 + if(typeId->getTag() == members[i-1]->getTag() + 1) { + genTag = false; + } + else { + genTag = true; + } + } + + if(genTag) { + s+=genratePrefix(typeId) + " "; + } + + + s += toStr(typeId->getTypePtr()); + } + return "struct<" + s + ">"; +} + +string Tars2Case::tocaseStruct(const StructPtr &pPtr, const string& varName) const +{ + vector& members = pPtr->getAllMemberPtr(); + string s = string("<"); + + for(size_t i = 0; i < members.size(); i++) { + if(i != 0) { + s += ","; + } + s += toCase(members[i]->getTypePtr(), varName); + } + s += ">"; + return s; +} + +string Tars2Case::genratePrefix(const TypeIdPtr &ptr) const +{ + string s = TC_Common::tostr(ptr->getTag()) + " "; + if(ptr->isRequire()) { + s += "require"; + } + else { + s += "optional"; + } + return s; +} + +string Tars2Case::tostrEnum(const EnumPtr &pPtr) const +{ + return "int"; +} + +string Tars2Case::tocaseEnum(const EnumPtr &pPtr, const string& varName) const +{ + return "19"; +} + + +string Tars2Case::generateTest(const ParamDeclPtr &pPtr) const +{ + ostringstream s; + + TypePtr typePtr = pPtr->getTypeIdPtr()->getTypePtr(); + s << toStr(typePtr); + return s.str(); +} + +string Tars2Case::generateCase(const ParamDeclPtr &pPtr) const +{ + ostringstream s; + + TypePtr typePtr = pPtr->getTypeIdPtr()->getTypePtr(); + string varName = pPtr->getTypeIdPtr()->getId(); + s << toCase(typePtr, varName); + return s.str(); +} + +struct SortOperation +{ + bool operator()(const OperationPtr &o1, const OperationPtr &o2) + { + return o1->getId() < o2->getId(); + } +}; + + +string Tars2Case::generateTest(const InterfacePtr &pPtr, const string& outfile) const +{ + ostringstream s; + vector& vOperation = pPtr->getAllOperationPtr(); + std::sort(vOperation.begin(), vOperation.end(), SortOperation()); + + //生成客户端接口的声明 + TC_File::makeDirRecursive(_baseDir); + for (size_t i = 0; i < vOperation.size(); i++) + { + string sCase = ""; + string sInParams = ""; + string sOutParams = ""; + + vector& vParamDecl = vOperation[i]->getAllParamDeclPtr(); + for (size_t j = 0; j < vParamDecl.size(); j++) + { + if(vParamDecl[j]->isOut()) { + sOutParams += (sOutParams.empty() ? "" : "|") + generateTest(vParamDecl[j]); + } + else { + sCase += (sCase.empty() ? "" : "\r\n") + generateCase(vParamDecl[j]); + sInParams += (sInParams.empty() ? "" : "|") + generateTest(vParamDecl[j]); + } + } + + ostringstream sc; + sc << sInParams << endl << "#### 隔离符 ####" << endl << sCase << endl; + string filecase = _baseDir + "/" + vOperation[i]->getId() + ".case"; + TC_File::save2file(filecase, sc.str()); + } + return s.str(); +} + +JsonValuePtr Tars2Case::toJsonBuiltin(const BuiltinPtr &pPtr) const +{ + JsonValuePtr p; + switch (pPtr->kind()) + { + case Builtin::KindBool: + p = JsonOutput::writeJson(true); + break; + case Builtin::KindByte: + p = JsonOutput::writeJson(8); + break; + case Builtin::KindShort: + p = JsonOutput::writeJson(16); + break; + case Builtin::KindInt: + p = JsonOutput::writeJson(32); + break; + case Builtin::KindLong: + p = JsonOutput::writeJson(64); + break; + case Builtin::KindFloat: + p = JsonOutput::writeJson(1.01); + break; + case Builtin::KindDouble: + p = JsonOutput::writeJson((double)2.0000005); + break; + case Builtin::KindString: + p = JsonOutput::writeJson(string("string")); + break; + default: + assert(false); + break; + } + return p; +} + +JsonValuePtr Tars2Case::toJsonEnum(const EnumPtr &pPtr) const +{ + return JsonOutput::writeJson(string("int32")); +} + +JsonValueArrayPtr Tars2Case::toJsonVector(const VectorPtr &pPtr) const +{ + JsonValueArrayPtr p = new JsonValueArray(); + + JsonValuePtr p1 = generateJson(pPtr->getTypePtr()); + p->push_back(p1); + p->push_back(p1); + return p; +} + +JsonValueObjPtr Tars2Case::toJsonMap(const MapPtr &pPtr) const +{ + JsonValueObjPtr p = new JsonValueObj(); + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getLeftTypePtr()); + if (bPtr) + { + p->value["key"] = generateJson(pPtr->getRightTypePtr()); + // p->value[tocaseBuiltin(bPtr, "")] = generateJson(pPtr->getRightTypePtr()); + } + return p; +} + +JsonValueObjPtr Tars2Case::toJsonStruct(const StructPtr &pPtr) const +{ + JsonValueObjPtr p = new JsonValueObj(); + vector& members = pPtr->getAllMemberPtr(); + + //是否生成tag和require等信息 + for(size_t i = 0; i < members.size(); i++) + { + TypeIdPtr typeId = members[i]; + string keyName = typeId->getId(); + p->value[keyName] = generateJson(typeId->getTypePtr()); + } + return p; +} + + +JsonValuePtr Tars2Case::generateJson(const TypePtr &pPtr) const +{ + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); + if (bPtr) return toJsonBuiltin(bPtr); + + VectorPtr vPtr = VectorPtr::dynamicCast(pPtr); + if (vPtr) return toJsonVector(vPtr); + + MapPtr mPtr = MapPtr::dynamicCast(pPtr); + if (mPtr) return toJsonMap(mPtr); + + StructPtr sPtr = StructPtr::dynamicCast(pPtr); + if (sPtr) return toJsonStruct(sPtr); + + EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); + if (ePtr) return toJsonEnum(ePtr); + + assert(false); + return NULL; +} + +JsonValuePtr Tars2Case::toJsonDescEnum(const EnumPtr &pPtr) const +{ + return JsonOutput::writeJson(string("0")); +} + +JsonValuePtr Tars2Case::toJsonDescVector(const VectorPtr &pPtr) const +{ + JsonValueObjPtr p = new JsonValueObj(); + string name = "0_vector_" + toDescStr(pPtr->getTypePtr()); + p->value[name] = generateJsonDesc(pPtr->getTypePtr()); + return p; +} + +JsonValuePtr Tars2Case::toJsonDescMap(const MapPtr &pPtr) const +{ + string name; + JsonValueObjPtr p = new JsonValueObj(); + name = "0_map_" + toDescStr(pPtr->getLeftTypePtr()); + p->value[name] = generateJsonDesc(pPtr->getLeftTypePtr()); + name = "1_map_" + toDescStr(pPtr->getRightTypePtr()); + p->value[name] = generateJsonDesc(pPtr->getRightTypePtr()); + return p; +} + +JsonValuePtr Tars2Case::toJsonDescStruct(const StructPtr &pPtr) const +{ + JsonValueObjPtr p = new JsonValueObj(); + vector& members = pPtr->getAllMemberPtr(); + + //是否生成tag和require等信息 + for(size_t i = 0; i < members.size(); i++) + { + ostringstream osd; + osd << members[i]->getTag() << "_" << members[i]->getId() << "_" << toDescStr(members[i]->getTypePtr()); + p->value[osd.str()] = generateJsonDesc(members[i]); + } + return p; +} + +JsonValuePtr Tars2Case::generateJsonDesc(const TypePtr &pPtr) const +{ + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); + if (bPtr) return JsonOutput::writeJson(bPtr->def()); + + VectorPtr vPtr = VectorPtr::dynamicCast(pPtr); + if (vPtr) return toJsonDescVector(vPtr); + + MapPtr mPtr = MapPtr::dynamicCast(pPtr); + if (mPtr) return toJsonDescMap(mPtr); + + StructPtr sPtr = StructPtr::dynamicCast(pPtr); + if (sPtr) return toJsonDescStruct(sPtr); + + EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); + if (ePtr) return toJsonDescEnum(ePtr); + + assert(false); + return NULL; +} + +JsonValuePtr Tars2Case::generateJsonDesc(const TypeIdPtr &pPtr) const +{ + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr()); + if (bPtr) return JsonOutput::writeJson(pPtr->hasDefault() ? pPtr->def() : bPtr->def()); + return generateJsonDesc(pPtr->getTypePtr()); +} + +string Tars2Case::generateDesc(const InterfacePtr &pPtr, const string& outfile) const +{ + ostringstream s; + vector& vOperation = pPtr->getAllOperationPtr(); + std::sort(vOperation.begin(), vOperation.end(), SortOperation()); + + //生成客户端接口的声明 + TC_File::makeDirRecursive(_baseDir); + for (size_t i = 0; i < vOperation.size(); i++) + { + JsonValueObjPtr inDesc = new JsonValueObj(); + JsonValueObjPtr inParam = new JsonValueObj(); + + vector& vParamDecl = vOperation[i]->getAllParamDeclPtr(); + for (size_t j = 0; j < vParamDecl.size(); j++) + { + ostringstream osd; + TypeIdPtr& p = vParamDecl[j]->getTypeIdPtr(); + osd << p->getTag() << "_" << p->getId() << "_" << toDescStr(p->getTypePtr()); + if(!vParamDecl[j]->isOut()) + { + inDesc->value[osd.str()] = generateJsonDesc(p); + inParam->value[p->getId()] = generateJson(vParamDecl[j]->getTypeIdPtr()->getTypePtr()); + } + } + + string filedesc = _baseDir + "/" + vOperation[i]->getId() + ".desc"; + string filecase = _baseDir + "/" + vOperation[i]->getId() + ".case"; + TC_File::save2file(filedesc, TC_Json::writeValue(inDesc)); + TC_File::save2file(filecase, TC_Json::writeValue(inParam)); + } + return s.str(); +} + +string Tars2Case::generateJson(const InterfacePtr &pPtr, const string& outfile) const +{ + ostringstream s; + + vector& vOperation = pPtr->getAllOperationPtr(); + std::sort(vOperation.begin(), vOperation.end(), SortOperation()); + + // 生成客户端接口的声明 + JsonValueObjPtr v = new JsonValueObj(); + // JsonValueArrayPtr v = new JsonValueArray(); + for (size_t i = 0; i < vOperation.size(); i++) + { + string intCaseValues = ""; + string intCaseParams = ""; + string outCaseParams = ""; + + JsonValueObjPtr inDesc = new JsonValueObj(); + JsonValueObjPtr outDesc = new JsonValueObj(); + JsonValueObjPtr inParam = new JsonValueObj(); + JsonValueObjPtr outParam = new JsonValueObj(); + + vector& vParamDecl = vOperation[i]->getAllParamDeclPtr(); + for (size_t j = 0; j < vParamDecl.size(); j++) + { + ostringstream osd; + TypeIdPtr& p = vParamDecl[j]->getTypeIdPtr(); + osd << p->getTag() << "_" << p->getId() << "_" << toDescStr(p->getTypePtr()); + + if(vParamDecl[j]->isOut()) + { + outCaseParams += (outCaseParams.empty() ? "" : "|") + generateTest(vParamDecl[j]); + outDesc->value[osd.str()] = generateJsonDesc(p->getTypePtr()); + outParam->value[p->getId()] = generateJson(p->getTypePtr()); + } + else + { + intCaseValues += (intCaseValues.empty() ? "" : "
") + generateCase(vParamDecl[j]); + intCaseParams += (intCaseParams.empty() ? "" : "|") + generateTest(vParamDecl[j]); + inDesc->value[osd.str()] = generateJsonDesc(p->getTypePtr()); + inParam->value[p->getId()] = generateJson(vParamDecl[j]->getTypeIdPtr()->getTypePtr()); + } + } + + JsonValueObjPtr p = new JsonValueObj(); + p->value["funinput"] = inParam; + p->value["funoutput"] = outParam; + p->value["descinput"] = inDesc; + p->value["descoutput"] = outDesc; + p->value["rettype"] = JsonOutput::writeJson(toStr(vOperation[i]->getReturnPtr()->getTypePtr())); + p->value["funintpara"] = JsonOutput::writeJson(intCaseParams); + p->value["funintvals"] = JsonOutput::writeJson(intCaseValues); + p->value["funoutpara"] = JsonOutput::writeJson(outCaseParams); + v->value[vOperation[i]->getId()] = JsonValuePtr::dynamicCast(p); + } + + if (_baseDir.empty()) + { + cout << TC_Json::writeValue(v) << endl; + } + else + { + string filetest = _baseDir + "/" + (outfile.empty() ? pPtr->getId() : outfile) + ".json"; + TC_File::makeDirRecursive(_baseDir); + TC_File::save2file(filetest, TC_Json::writeValue(v)); + } + return TC_Json::writeValue(v); +} + +/******************************Tars2Case***************************************/ +void Tars2Case::generateFile(const ContextPtr &pPtr, const string& outfile) const +{ + ostringstream s; + + vector namespaces = pPtr->getNamespaces(); + for (size_t i = 0; i < namespaces.size(); i++) + { + vector &is = namespaces[i]->getAllInterfacePtr(); + for (size_t j = 0; j < is.size(); j++) + { + if (_webCase) + { + // 生成TarsWeb需要的用例 + generateJson(is[j], outfile); + } + else if (_jsonCase) + { + generateDesc(is[j], outfile); + } + else + { + // 生成Tars压测用例的文件 + generateTest(is[j], outfile); + } + } + } +} + +void Tars2Case::createFile(const string &tarsfile, const string& outfile) +{ + std::vector contexts = g_parse->getContexts(); + for (size_t i = 0; i < contexts.size(); i++) + { + if (tarsfile == contexts[i]->getFileName()) + { + generateFile(contexts[i], outfile); + } + } +} + +void Tars2Case::setBaseDir(const string &dir) +{ + _baseDir = dir; +} + +void Tars2Case::setJsonCase(bool jsonCase) +{ + _jsonCase = jsonCase; +} + +void Tars2Case::setWebSupport(bool webCase) +{ + _webCase = webCase; +} + +string Tars2Case::getFilePath(const string &ns) const +{ + return _baseDir + "/" + ns + "/"; +} diff --git a/tools/tars2case/tars2case.h b/tools/tars2case/tars2case.h new file mode 100755 index 0000000000000000000000000000000000000000..6c7158073a429dbad25d1544650c1f4b8b50db0b --- /dev/null +++ b/tools/tars2case/tars2case.h @@ -0,0 +1,239 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT 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 __TARS2CASE_H_ +#define __TARS2CASE_H_ + +#include "parse.h" +#include "util/tc_common.h" +#include "util/tc_option.h" +#include "tup/Tars.h" +#include "tup/TarsJson.h" + +#include +#include + + +using namespace tars; +/** + * 根据jce生成自动测试的字符串 + */ +class Tars2Case +{ +public: + Tars2Case(); + + /** + * 设置代码生成的根目录 + * @param dir + */ + void setBaseDir(const string &dir); + + /** + * 生成JSON2TARS用例 + * @param jsonCase + */ + void setJsonCase(bool jsonCase); + + /** + * 生成WEB平台需要的用例 + * @param webCase + */ + void setWebSupport(bool webCase); + + /** + * 生成 + * @param file + * @param isFramework 是否是框架 + */ + void createFile(const string &tarsfile, const string& outfile = ""); + +protected: + /** + * 根据命名空间获取文件路径 + * @param ns 命名空间 + * + * @return string + */ + string getFilePath(const string &ns) const; + + string _baseDir; + bool _jsonCase; + bool _webCase; + + //下面是类型描述的源码生成 +protected: + /** + * 生成某类型的字符串描述源码 + * @param pPtr + * + * @return string + */ + string toStr(const TypePtr &pPtr) const; + + + /** + * 生成某类型的字符串描述源码 + * @param pPtr + * + * @return string + */ + string toDescStr(const TypePtr &pPtr) const; + + /** + * 生成内建类型的字符串源码 + * @param pPtr + * + * @return string + */ + string tostrBuiltin(const BuiltinPtr &pPtr) const; + /** + * 生成vector的字符串描述 + * @param pPtr + * + * @return string + */ + string tostrVector(const VectorPtr &pPtr) const; + + /** + * 生成map的字符串描述 + * @param pPtr + * + * @return string + */ + string tostrMap(const MapPtr &pPtr, bool bNew = false) const; + + /** + * 生成某种结构的符串描述 + * @param pPtr + * + * @return string + */ + string tostrStruct(const StructPtr &pPtr) const; + + /** + * 生成某种枚举的符串描述 + * @param pPtr + * + * @return string + */ + string tostrEnum(const EnumPtr &pPtr) const; + +protected: + /** + * 生成某类型的JSON描述源码 + * @param pPtr + * + * @return string + */ + JsonValuePtr generateJson(const TypePtr &pPtr) const; + + JsonValuePtr toJsonBuiltin(const BuiltinPtr &pPtr) const; + + JsonValuePtr toJsonEnum(const EnumPtr &pPtr) const; + + JsonValueObjPtr toJsonMap(const MapPtr &pPtr) const; + + JsonValueObjPtr toJsonStruct(const StructPtr &pPtr) const; + + JsonValueArrayPtr toJsonVector(const VectorPtr &pPtr) const; + + JsonValuePtr generateJsonDesc(const TypeIdPtr &pPtr) const; + + JsonValuePtr generateJsonDesc(const TypePtr &pPtr) const; + + JsonValuePtr toJsonDescEnum(const EnumPtr &pPtr) const; + + JsonValuePtr toJsonDescMap(const MapPtr &pPtr) const; + + JsonValuePtr toJsonDescStruct(const StructPtr &pPtr) const; + + JsonValuePtr toJsonDescVector(const VectorPtr &pPtr) const; + +protected: + + string tocaseBuiltin(const BuiltinPtr &pPtr, const string& varName) const; + + string tocaseVector(const VectorPtr &pPtr, const string& varName) const; + + string tocaseMap(const MapPtr &pPtr, const string& varName) const; + + string tocaseStruct(const StructPtr &pPtr, const string& varName) const; + + string tocaseEnum(const EnumPtr &pPtr, const string& varName) const; + + string toCase(const TypePtr &pPtr, const string& varName) const; + + //以下是h和java文件的具体生成 +protected: + /** + * 生成参数声明的test文件内容 + * @param pPtr + * + * @return string + */ + string generateTest(const ParamDeclPtr &pPtr) const; + + /** + * + * 生成测试用例 + **/ + string generateCase(const ParamDeclPtr &pPtr) const; + + /** + * 生成WEB代理请求访问的JSON串 + * @param pPtr + * @param outfile + * + * @return string + */ + string generateJson(const InterfacePtr &pPtr, const string& outfile = "") const; + + /** + * 生成WEB代理请求访问的JSON串, JSON用例 + * @param pPtr + * @param outfile + * + * @return string + */ + string generateDesc(const InterfacePtr &pPtr, const string& outfile = "") const; + + /** + * 生成TEST接口访问的测试 + * @param pPtr + * @param outfile + * + * @return string + */ + string generateTest(const InterfacePtr &pPtr, const string& outfile = "") const; + + /** + * 生成每个tars文件的用例文件 + * @param pPtr + * + * @return string + */ + void generateFile(const ContextPtr &pPtr, const string& outfile = "") const; + + /** + * 生成tag和require、optional信息 + */ + string genratePrefix(const TypeIdPtr &ptr) const; +}; + +#endif + + diff --git a/tools/tars2cpp/CMakeLists.txt b/tools/tars2cpp/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/tools/tars2cpp/main.cpp b/tools/tars2cpp/main.cpp old mode 100644 new mode 100755 index 119843bcfeb49268d591083eab96c020a548a109..ff8be2bda9f2642568f00997df0d32f563c1e95a --- a/tools/tars2cpp/main.cpp +++ b/tools/tars2cpp/main.cpp @@ -111,6 +111,35 @@ int main(int argc, char* argv[]) t2c.setJsonSupport(false); } + if (option.hasParam("sql")) + { + t2c.setSqlSupport(true); + t2c.setJsonSupport(true); + } + + if (option.hasParam("xml")) + { + vector vXmlIntf; + string sXml = tars::TC_Common::trim(option.getValue("xml")); + sXml = tars::TC_Common::trimleft(tars::TC_Common::trimright(sXml, "]"), "["); + if (!sXml.empty()) + { + vXmlIntf = tars::TC_Common::sepstr(sXml, ",", false); + } + t2c.setXmlSupport(true, vXmlIntf); + } + + if (option.hasParam("json")) + { + t2c.setJsonSupport(true); + string sJson = tars::TC_Common::trim(option.getValue("json")); + sJson = tars::TC_Common::trimleft(tars::TC_Common::trimright(sJson, "]"), "["); + if (!sJson.empty()) + { + t2c.setJsonSupport(tars::TC_Common::sepstr(sJson, ",", false)); + } + } + t2c.setTarsMaster(option.hasParam("tarsMaster")); try diff --git a/tools/tars2cpp/tars2cpp.cpp b/tools/tars2cpp/tars2cpp.cpp old mode 100644 new mode 100755 index 173a59ef099d95244fbcf4e4ad3affd5b9df6f12..fe6b6d97c6c9b5a6f3f25baff1d907ee482f7c6e --- a/tools/tars2cpp/tars2cpp.cpp +++ b/tools/tars2cpp/tars2cpp.cpp @@ -3,14 +3,14 @@ * * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. * - * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * https://opensource.org/licenses/BSD-3-Clause * - * Unless required by applicable law or agreed to in writing, software distributed - * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ @@ -29,6 +29,8 @@ Tars2Cpp::Tars2Cpp() : _checkDefault(false) , _onlyStruct(false) +, _bSqlSupport(false) +, _bXmlSupport(false) , _bJsonSupport(true) , _namespace("tars") // , _unknownField(false) @@ -37,6 +39,182 @@ Tars2Cpp::Tars2Cpp() } +string Tars2Cpp::writeToXml(const TypeIdPtr &pPtr) const +{ + ostringstream s; + if(EnumPtr::dynamicCast(pPtr->getTypePtr())) + { + s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace+ "::XmlOutput::writeXml((" + _namespace+ "::Int32)" << pPtr->getId() << ", _cdata_format);" << endl; + } + else if(pPtr->getTypePtr()->isArray()) + { + s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace+ "::XmlOutput::writeXml((const " + << tostr(pPtr->getTypePtr()) << " *)" << pPtr->getId() << "Len" << ");" << endl; + } + else if(pPtr->getTypePtr()->isPointer()) + { + s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace+ "::XmlOutput::writeXml((const " + << tostr(pPtr->getTypePtr()) << " )" << pPtr->getId() << "Len" << ");" << endl; + } + else + { + MapPtr mPtr = MapPtr::dynamicCast(pPtr->getTypePtr()); + VectorPtr vPtr = VectorPtr::dynamicCast(pPtr->getTypePtr()); + if (!_checkDefault || pPtr->isRequire() || (!pPtr->hasDefault() && !mPtr && !vPtr)) + { + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr()); + if (pPtr->getTypePtr()->isSimple() || (bPtr && bPtr->kind() == Builtin::KindString)) + { + s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace + "::XmlOutput::writeXml(" << pPtr->getId() << ", _cdata_format);" << endl; + } + else + { + s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace + "::XmlOutput::writeXml(" << pPtr->getId() << ");" << endl; + } + } + else + { + string sDefault = pPtr->def(); + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr()); + if (bPtr && bPtr->kind() == Builtin::KindString) + { + sDefault = "\"" + TC_Common::replace(pPtr->def(), "\"", "\\\"") + "\""; + } + + if (mPtr || vPtr) + { + s << TAB << "if (" << pPtr->getId() << ".size() > 0)" << endl; + } + else + { + s << TAB << "if (" << pPtr->getId() << " != " << sDefault << ")" << endl; + } + + s << TAB << "{" << endl; + INC_TAB; + s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace+ "::XmlOutput::writeXml(" << pPtr->getId() << ");" << endl; + DEL_TAB; + s << TAB << "}" << endl; + } + } + + return s.str(); +} + +string Tars2Cpp::readFromXml(const TypeIdPtr &pPtr, bool bIsRequire) const +{ + ostringstream s; + if(EnumPtr::dynamicCast(pPtr->getTypePtr())) + { + s << TAB << "tars::XmlInput::readXml((tars::Int32&)" << pPtr->getId() <<", pObj->value[\"" << pPtr->getId() << "\"]"; + } + else if(pPtr->getTypePtr()->isArray()) + { + s << TAB << "tars::XmlInput::readXml(" << pPtr->getId() << "Len" <<", pObj->value[\"" << pPtr->getId() << "\"]" << getSuffix(pPtr); + } + else if(pPtr->getTypePtr()->isPointer()) + { + // "not support"; + } + else + { + s << TAB << "tars::XmlInput::readXml(" << pPtr->getId() << ",pObj->value[\"" << pPtr->getId() << "\"]"; + } + s << ", " << ((pPtr->isRequire() && bIsRequire)?"true":"false") << ");" << endl; + + return s.str(); +} + +string Tars2Cpp::writeToSql(const TypeIdPtr &pPtr) const +{ + ostringstream s; + if(EnumPtr::dynamicCast(pPtr->getTypePtr())) + { + s << TAB << "_mycols[\"" << pPtr->getId() << "\"] = make_pair(tars::TC_Mysql::DB_INT, tars::TC_Common::tostr(" << pPtr->getId() << "));" << endl; + } + + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr()); + if (bPtr) + { + switch(bPtr->kind()) + { + case Builtin::KindBool: + case Builtin::KindByte: + case Builtin::KindShort: + case Builtin::KindInt: + case Builtin::KindLong: + s << TAB << "_mycols[\"" << pPtr->getId() << "\"] = make_pair(tars::TC_Mysql::DB_INT, tars::TC_Common::tostr(" << pPtr->getId() << "));" << endl; + break; + case Builtin::KindFloat: + case Builtin::KindDouble: + s << TAB << "_mycols[\"" << pPtr->getId() << "\"] = make_pair(tars::TC_Mysql::DB_STR, tars::TC_Common::tostr(" << pPtr->getId() << "));" << endl; + break; + case Builtin::KindString: + s << TAB << "_mycols[\"" << pPtr->getId() << "\"] = make_pair(tars::TC_Mysql::DB_STR, tars::TC_Common::trim(" << pPtr->getId() << "));" << endl; + break; + default: + break; + } + } + else if (!pPtr->getTypePtr()->isSimple()) + { + s << TAB << "_mycols[\"" << pPtr->getId() << "\"] = make_pair(tars::TC_Mysql::DB_STR, tars::TC_Json::writeValue(tars::JsonOutput::writeJson(" << pPtr->getId() << ")));" << endl; + } + + return s.str(); +} + +string Tars2Cpp::readFromSql(const TypeIdPtr &pPtr, bool bIsRequire) const +{ + ostringstream s; + EnumPtr ePtr = EnumPtr::dynamicCast(pPtr->getTypePtr()); + if(ePtr) + { + s << TAB << pPtr->getId() << " = (" << ePtr->getSid() <<")TC_Common::strto(_mysrd[\"" << pPtr->getId() << "\"]);" << endl; + } + + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr()); + if (bPtr) + { + switch(bPtr->kind()) + { + case Builtin::KindBool: + s << TAB << pPtr->getId() << " = TC_Common::strto(_mysrd[\"" << pPtr->getId() << "\"]);" << endl; + break; + case Builtin::KindByte: + s << TAB << pPtr->getId() << " = TC_Common::strtoisUnsigned() ? "UInt8" : "Char") << ">(_mysrd[\"" << pPtr->getId() << "\"]);" << endl; + break; + case Builtin::KindShort: + s << TAB << pPtr->getId() << " = TC_Common::strtoisUnsigned() ? "UInt16" : "Short") << ">(_mysrd[\"" << pPtr->getId() << "\"]);" << endl; + break; + case Builtin::KindInt: + s << TAB << pPtr->getId() << " = TC_Common::strtoisUnsigned() ? "UInt32" : "Int32") << ">(_mysrd[\"" << pPtr->getId() << "\"]);" << endl; + break; + case Builtin::KindLong: + s << TAB << pPtr->getId() << " = TC_Common::strtoisUnsigned() ? "UInt64" : "Int64") << ">(_mysrd[\"" << pPtr->getId() << "\"]);" << endl; + break; + case Builtin::KindFloat: + s << TAB << pPtr->getId() << " = TC_Common::strto(_mysrd[\"" << pPtr->getId() << "\"]);" << endl; + break; + case Builtin::KindDouble: + s << TAB << pPtr->getId() << " = TC_Common::strto(_mysrd[\"" << pPtr->getId() << "\"]);" << endl; + break; + case Builtin::KindString: + s << TAB << pPtr->getId() << " = TC_Common::trim(_mysrd[\"" << pPtr->getId() << "\"]);" << endl; + break; + default: + break; + } + } + else if (!pPtr->getTypePtr()->isSimple() ) + { + s << TAB << "tars::JsonInput::readJson(" << pPtr->getId() << ", tars::TC_Json::getValue(_mysrd[\"" << pPtr->getId() << "\"]), false);" << endl; + } + + return s.str(); +} + + string Tars2Cpp::writeToJson(const TypeIdPtr& pPtr) const { ostringstream s; @@ -47,13 +225,22 @@ string Tars2Cpp::writeToJson(const TypeIdPtr& pPtr) const } else if (pPtr->getTypePtr()->isArray()) { + /* s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace + "::JsonOutput::writeJson((const " << tostr(pPtr->getTypePtr()) << " *)" << pPtr->getId() << "Len" << ");" << endl; + */ + s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace + "::JsonOutput::writeJson((const " + << tostr(pPtr->getTypePtr()) << " *)" << pPtr->getId() << ", "<< pPtr->getId() << "Len" << ");" << endl; } else if (pPtr->getTypePtr()->isPointer()) { + /* s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace + "::JsonOutput::writeJson((const " << tostr(pPtr->getTypePtr()) << " )" << pPtr->getId() << "Len" << ");" << endl; + */ + s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace + "::JsonOutput::writeJson((const " + << tostr(pPtr->getTypePtr()) << " )" << pPtr->getId() << ", "<< pPtr->getId() << "Len" << ");" << endl; + } else { @@ -109,10 +296,11 @@ string Tars2Cpp::readFromJson(const TypeIdPtr& pPtr, bool bIsRequire) const // s << TAB << _namespace + "::JsonInput::readJson((" + _namespace + "::Int32&)" << pPtr->getId() << ",pObj->value[\"" << pPtr->getId() << "\"]"; // } // else - + if (pPtr->getTypePtr()->isArray()) { - s << TAB << _namespace + "::JsonInput::readJson(" << pPtr->getId() << "Len" << ",pObj->value[\"" << pPtr->getId() << "\"]" << getSuffix(pPtr); + //s << TAB << _namespace + "::JsonInput::readJson(" << pPtr->getId() << "Len" << ",pObj->value[\"" << pPtr->getId() << "\"]" << getSuffix(pPtr); + s << TAB << _namespace + "::JsonInput::readJson(" << pPtr->getId() << ", " << "sizeof("+pPtr->getId()+")" << ", " << pPtr->getId() << "Len" << ", pObj->value[\"" << pPtr->getId() << "\"]"; } else if (pPtr->getTypePtr()->isPointer()) { @@ -203,7 +391,8 @@ string Tars2Cpp::readFrom(const TypeIdPtr& pPtr, bool bIsRequire) const } else if (pPtr->getTypePtr()->isArray()) { - s << TAB << "_is.read(" << pPtr->getId() << ", " << getSuffix(pPtr) << ", " << pPtr->getId() << "Len"; + //s << TAB << "_is.read(" << pPtr->getId() << ", " << getSuffix(pPtr) << ", " << pPtr->getId() << "Len"; + s << TAB << "_is.read(" << pPtr->getId() << ", " << "sizeof("+pPtr->getId()+")" << ", " << pPtr->getId() << "Len"; } else if (pPtr->getTypePtr()->isPointer()) { @@ -507,13 +696,16 @@ string Tars2Cpp::generateH(const StructPtr& pPtr, const string& namespaceId) con //////////////////////////////////////////////////////////// //定义缺省构造函数 s << TAB << pPtr->getId() << "()" << endl; - + s << TAB << "{" << endl; + INC_TAB; + s << TAB << "resetDefautlt();" << endl; vector& member = pPtr->getAllMemberPtr(); + +/* bool b = false; //定义初始化列表 for (size_t j = 0; j < member.size(); j++) { - if (member[j]->getTypePtr()->isArray()) { if (!b) s << TAB << ":"; @@ -596,9 +788,18 @@ string Tars2Cpp::generateH(const StructPtr& pPtr, const string& namespaceId) con } s << TAB << "memset(" << member[j]->getId() << ", 0, " << "sizeof(" << member[j]->getId() << "));" << endl; } + + */ + + if (_bXmlSupport) + { + s << TAB << "_cdata_format = false;" << endl; + } + DEL_TAB; s << TAB << "}" << endl; + //resetDefault()函数 s << TAB << "void resetDefautlt()" << endl; s << TAB << "{" << endl; @@ -730,6 +931,86 @@ string Tars2Cpp::generateH(const StructPtr& pPtr, const string& namespaceId) con s << TAB << "}" << endl; } + if (_bXmlSupport) + { + s << TAB << "void setXmlFormat(bool cdata = false)" << endl; + s << TAB << "{" << endl; + INC_TAB; + s << TAB << "_cdata_format = cdata;" <getType() != eXmlTypeObj)" << endl; + s << TAB << "{" << endl; + INC_TAB; + s << TAB << "char s[128];" << endl; + s << TAB << "snprintf(s, sizeof(s), \"read 'struct' type mismatch, get type: %d.\", p->getType());" << endl; + s << TAB << "throw TC_Xml_Exception(s);" << endl; + DEL_TAB; + s << TAB << "}" << endl; + s << TAB << "tars::XmlValueObjPtr pObj= tars::XmlValueObjPtr::dynamicCast(p);" << endl; + for(size_t j = 0; j < member.size(); j++) + { + s << readFromXml(member[j]); + } + DEL_TAB; + s << TAB << "}" << endl; + + s << TAB << "void readFromXmlString(const string & str)" << endl; + s << TAB << "{" << endl; + INC_TAB; + s << TAB << "readFromXml(tars::TC_Xml::getValue(str));" <getTypePtr()) << " " << member[j]->getId() << toStrSuffix(member[j]) << ";" << endl; } + + if (_bXmlSupport) + { + DEL_TAB; + s << TAB << "private:" << endl; + INC_TAB; + s << TAB << "bool _cdata_format;" << endl; + } + // if (_unknownField) // { // s << TAB << "std::string sUnknownField;" << endl; @@ -1284,6 +1574,58 @@ string Tars2Cpp::generateServantDispatch(const OperationPtr& pPtr, const string& } DEL_TAB; s << TAB << "}" << endl; + + // 支持JSON协议分发 + if (_bJsonSupport && tars::TC_Common::matchPeriod(pPtr->getId(), _vJsonIntf)) + { + s << TAB << "else if (_current->getRequestVersion() == JSONVERSION)" << endl; + s << TAB << "{" << endl; + INC_TAB; + s << TAB << _namespace << "::JsonValueObjPtr _jsonPtr = " << _namespace << "::JsonValueObjPtr::dynamicCast(" << _namespace << "::TC_Json::getValue(_current->getRequestBuffer()));" << endl; + for(size_t i = 0; i < vParamDecl.size(); i++) + { + string sParamName = vParamDecl[i]->getTypeIdPtr()->getId(); + string sEnum2Int = (EnumPtr::dynamicCast(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) ? "(" + _namespace + "::Int32)" : ""; + if (!vParamDecl[i]->isOut()) + { + // tars::JsonInput::readJson(uin, _jsonPtr->value["uin"], true); 枚举类型转成int + s << TAB << _namespace << "::JsonInput::readJson(" << sParamName << ", _jsonPtr->value[\"" << sParamName << "\"], true);" << endl; + } + else + { + s << TAB << _namespace << "::JsonInput::readJson(" << sParamName << ", _jsonPtr->value[\"" << sParamName << "\"], false);" << endl; + } + } + DEL_TAB; + s << TAB << "}" << endl; + } + + // 支持XML协议分发 + if (_bXmlSupport && tars::TC_Common::matchPeriod(pPtr->getId(), _vXmlIntf)) + { + s << TAB << "else if (_current->getRequestVersion() == XMLVERSION)" << endl; + s << TAB << "{" << endl; + INC_TAB; + + s << TAB << "tars::XmlValueObjPtr _xmlPtr = tars::XmlValueObjPtr::dynamicCast(tars::TC_Xml::getValue(_current->getRequestBuffer()));" << endl; + for(size_t i = 0; i < vParamDecl.size(); i++) + { + string sParamName = vParamDecl[i]->getTypeIdPtr()->getId(); + if(!vParamDecl[i]->isOut()) + { + //枚举类型转成int + s << TAB << "tars::XmlInput::readXml(" << sParamName << ", _xmlPtr->value[\"" << sParamName << "\"], true);" << endl; + } + else + { + s << TAB << "tars::XmlInput::readXml(" << sParamName << ", _xmlPtr->value[\"" << sParamName << "\"], false);" << endl; + } + } + + DEL_TAB; + s << TAB << "}" << endl; + } + s << TAB << "else" << endl; s << TAB << "{" << endl; INC_TAB; @@ -1346,6 +1688,70 @@ string Tars2Cpp::generateServantDispatch(const OperationPtr& pPtr, const string& DEL_TAB; s << TAB << "}" << endl; + + // 支持JSON协议分发 + if (_bJsonSupport && tars::TC_Common::matchPeriod(pPtr->getId(), _vJsonIntf)) + { + s << TAB << "else if (_current->getRequestVersion() == JSONVERSION)" << endl; + s << TAB << "{" << endl; + INC_TAB; + s << TAB << _namespace << "::JsonValueObjPtr _p = new " << _namespace << "::JsonValueObj();" << endl; + for(size_t i = 0; i < vParamDecl.size(); i++) + { + string sParamName = vParamDecl[i]->getTypeIdPtr()->getId(); + if (vParamDecl[i]->isOut()) + { + s << TAB << "_p->value[\"" << sParamName << "\"] = "<< _namespace << "::JsonOutput::writeJson(" << sParamName << ");" << endl; + } + } + + if (pPtr->getReturnPtr()->getTypePtr()) + { + BuiltinPtr retPtr = BuiltinPtr::dynamicCast(pPtr->getReturnPtr()->getTypePtr()); + if (retPtr->kind() >= Builtin::KindBool && retPtr->kind() <= Builtin::KindLong) + { + s << TAB << "_p->value[\"ret\"] = "<< _namespace << "::JsonOutput::writeJson(" << pPtr->getReturnPtr()->getId() << ");" << endl; + } + } + + s << TAB << _namespace << "::TC_Json::writeValue(_p, _sResponseBuffer);" << endl; + DEL_TAB; + s << TAB << "}" << endl; + } + + // 支持XML协议分发 + if (_bXmlSupport && tars::TC_Common::matchPeriod(pPtr->getId(), _vXmlIntf)) + { + s << TAB << "else if (_current->getRequestVersion() == XMLVERSION)" << endl; + s << TAB << "{" << endl; + INC_TAB; + + s << TAB << "tars::XmlValueObjPtr _p = new tars::XmlValueObj();" << endl; + + for(size_t i = 0; i < vParamDecl.size(); i++) + { + string sParamName = vParamDecl[i]->getTypeIdPtr()->getId(); + if (vParamDecl[i]->isOut()) + { + s << TAB << "_p->value[\"" << sParamName << "\"] = tars::XmlOutput::writeXml(" << sParamName << ");" << endl; + } + } + + if (pPtr->getReturnPtr()->getTypePtr()) + { + BuiltinPtr retPtr = BuiltinPtr::dynamicCast(pPtr->getReturnPtr()->getTypePtr()); + if (retPtr->kind() >= Builtin::KindBool && retPtr->kind() <= Builtin::KindLong) + { + s << TAB << "_p->value[\"ret\"] = tars::XmlOutput::writeXml(" << pPtr->getReturnPtr()->getId() << ");" << endl; + } + } + + s << TAB << "tars::TC_Xml::writeValue(_p, _sResponseBuffer);" << endl; + + DEL_TAB; + s << TAB << "}" << endl; + } + s << TAB << "else" << endl; //普通tars调用输出参数 @@ -1831,7 +2237,7 @@ string Tars2Cpp::generateHPromiseAsync(const InterfacePtr &pInter, const Operati s << TAB << "virtual void " << "callback_" << pPtr->getId() << "(const " << pInter->getId() << "PrxCallbackPromise::Promise" << sStruct << "Ptr &ptr)" << endl; s << TAB << "{" << endl; INC_TAB; - s << TAB << "_promise_" << sStruct << ".setValue(ptr);" << endl; + s << TAB << "_promise_" << sStruct << ".setValue(ptr);" << endl; DEL_TAB; s << TAB << "}" << endl; s << TAB << "virtual void " << "callback_" << pPtr->getId() << "_exception(" + _namespace + "::Int32 ret)" << endl; @@ -1839,7 +2245,7 @@ string Tars2Cpp::generateHPromiseAsync(const InterfacePtr &pInter, const Operati INC_TAB; s << TAB << "std::string str(\"\");" << endl; s << TAB << "str += \"Function:" << pPtr->getId() << "_exception|Ret:\";" << endl; - s << TAB << "str += TC_Common::tostr(ret);" << endl; + s << TAB << "str += TC_Common::tostr(ret);" << endl; s << TAB << "_promise_" << sStruct << ".setException(tars::copyException(str, ret));" << endl; DEL_TAB; s << TAB << "}" << endl; @@ -2457,6 +2863,8 @@ void Tars2Cpp::generateH(const ContextPtr &pPtr) const s << "#include " << endl; s << "#include \"tup/Tars.h\"" << endl; if (_bJsonSupport) s << "#include \"tup/TarsJson.h\"" << endl; + if (_bSqlSupport) s << "#include \"util/tc_mysql.h\"" << endl; + if (_bXmlSupport) s << "#include \"tup/TarsXml.h\"" << endl; s << "using namespace std;" << endl; @@ -2863,4 +3271,4 @@ StructPtr Tars2Cpp::findStruct(const ContextPtr& pPtr, const string& id) // s << endl; // s << "#endif" << endl; -// \ No newline at end of file +// diff --git a/tools/tars2cpp/tars2cpp.h b/tools/tars2cpp/tars2cpp.h old mode 100644 new mode 100755 index 3cfccd6899cb28b5733eeec1e461a8c6af428d29..43b07d014a8bdba0cc2f9396ef2d6cfbfeed9e7c --- a/tools/tars2cpp/tars2cpp.h +++ b/tools/tars2cpp/tars2cpp.h @@ -51,11 +51,30 @@ public: */ void setCheckDefault(bool bCheck) { _checkDefault = bCheck; } + /** + * 根据命令选项设置是否需要生成sql支持 + */ + void setSqlSupport(bool bSqlSupport) { _bSqlSupport = bSqlSupport;} + + /** + * 根据命令选项设置是否需要生成xml支持 + */ + void setXmlSupport(bool bXmlSupport, const vector& vXmlIntf) + { + _bXmlSupport = bXmlSupport; + _vXmlIntf = vXmlIntf; + } + /** * 根据命令选项设置是否需要生成json支持 */ void setJsonSupport(bool bJsonSupport) { _bJsonSupport = bJsonSupport; } + /** + * 根据命令选项设置是否需要生成json支持 + */ + void setJsonSupport(const vector& vJsonIntf) { _vJsonIntf = vJsonIntf; } + /** * 设置是否只生成struct */ @@ -74,6 +93,37 @@ public: //下面是编解码的源码生成 protected: + /** + * 生成xml + * @param pPtr + * + * @return string + */ + string writeToXml(const TypeIdPtr &pPtr) const; + + /** + * 生成xml + * @param pPtr + * + * @return string + */ + string readFromXml(const TypeIdPtr &pPtr, bool bIsRequire = true) const; + + /** + * 生成sql + * @param pPtr + * + * @return string + */ + string writeToSql(const TypeIdPtr &pPtr) const; + + /** + * 生成sql + * @param pPtr + * + * @return string + */ + string readFromSql(const TypeIdPtr &pPtr, bool bIsRequire = true) const; /** * 生成json @@ -449,8 +499,16 @@ private: bool _onlyStruct; + bool _bSqlSupport; + + bool _bXmlSupport; + bool _bJsonSupport; + vector _vJsonIntf; + vector _vXmlIntf; + + std::string _namespace ; // bool _unknownField; diff --git a/tools/tars2node/code_generator.cpp b/tools/tars2node/code_generator.cpp index 4236b21806a48538f73bb3b84401b53a62610dec..5d795676467c458fa7678b9dfc92b4819f83ab6d 100644 --- a/tools/tars2node/code_generator.cpp +++ b/tools/tars2node/code_generator.cpp @@ -21,8 +21,8 @@ string CodeGenerator::printHeaderRemark(const string &sTypeName) ostringstream s; s << "// **********************************************************************" << endl; s << "// Parsed By " << IDL_NAMESPACE_STR << "Parser(" << PARSER_VERSION << "), Generated By " << EXECUTE_FILENAME << "(" << GENERATOR_VERSION << ")" << endl; - s << "// " << IDL_NAMESPACE_STR << "Parser Maintained By and " << EXECUTE_FILENAME << " Maintained By " << endl; - s << "// Generated from \"" << TC_File::extractFileName(_sIdlFile) << "\" by " << + s << "// " << IDL_NAMESPACE_STR << "Parser Maintained By <" << TC_Common::upper(IDL_NAMESPACE_STR) << "> and " << EXECUTE_FILENAME << " Maintained By " << endl; + s << "// Generated from \"" << TC_File::extractFileName(_sIdlFile) << "\" by " << (_bEntry ? sTypeName : (_bMinimalMembers ? "Minimal" : "Relation")) << " Mode" << endl; s << "// **********************************************************************" << endl; s << endl; @@ -43,26 +43,47 @@ void CodeGenerator::createFile(const string &file, const bool bEntry) { if (_sIdlFile == contexts[i]->getFileName()) { - scan(_sIdlFile, true); //分析枚举值、结构体所在的文件 + scan(_sIdlFile, true); // collect idl symbols - if (!_bClient && !_bServer) + if (!_bClient && !_bServer) { - generateJS(contexts[i]); //生成当前文件的编解码文件 - if(_bDTS) generateDTS(contexts[i]); //生成 typescript 描述文件 + if (_bTS) + { + generateTS(contexts[i]); // generate .ts + } + else + { + generateJS(contexts[i]); // generate .js + if (_bDTS) generateDTS(contexts[i]); // generate .d.ts + } } - if (_bClient) + if (_bClient) { - if(!generateJSProxy(contexts[i])) return; //生成当前文件的客户端代理类文件 - if(_bDTS) generateDTSProxy(contexts[i]); //生成客户端 typescript 描述文件 + if (_bTS) + { + if (!generateTSProxy(contexts[i])) return; // generate .ts for proxy classes + } + else + { + if (!generateJSProxy(contexts[i])) return; // generate .js for proxy classes + if (_bDTS) generateDTSProxy(contexts[i]); // generate .d.ts for proxy classes + } } if (_bServer) { - if(!generateJSServer(contexts[i])) return; //生成当前文件的服务端代理类文件 - if(_bDTS) generateDTSServer(contexts[i]); //生成服务端 typescript 描述文件 - - generateJSServerImp(contexts[i]); //生成当前文件的服务端实现类文件 + if (_bTS) + { + if (!generateTSServer(contexts[i])) return; // generate .ts for server classes + generateTSServerImp(contexts[i]); // generate .ts for server implementations + } + else + { + if (!generateJSServer(contexts[i])) return; // generate .js for server classes + if (_bDTS) generateDTSServer(contexts[i]); // generate .d.ts for server classes + generateJSServerImp(contexts[i]); // generate .js for server implementations + } } vector files = contexts[i]->getIncludes(); @@ -74,10 +95,11 @@ void CodeGenerator::createFile(const string &file, const bool bEntry) node.setTargetPath(_sToPath); node.setRecursive(_bRecursive); node.setUseSpecialPath(_bUseSpecialPath); - node.setUseStringRepresent(_bUseStringRepresent); + node.setLongType(_iLongType); node.setStringBinaryEncoding(_bStringBinaryEncoding); node.setMinimalMembers(_bMinimalMembers); node.setDependent(_depMembers); + node.setEnableTS(_bTS); node.setEnableDTS(_bDTS); node.createFile(files[ii], false); diff --git a/tools/tars2node/code_generator.h b/tools/tars2node/code_generator.h index b98e8a0e185e6a90ac7fc06b0e34c0942660665a..57642701b98dbd3778fa24e640872ec2e353e608 100644 --- a/tools/tars2node/code_generator.h +++ b/tools/tars2node/code_generator.h @@ -60,6 +60,9 @@ #define PROTOCOL_COMPLEX PROTOCOL_V(IDL_NAMESPACE_STR, PROTOCOL_NAME, "COMPLEX") #define PROTOCOL_VAR TO_LOWER_STRING(PROTOCOL_NAME) +#define DISABLE_ESLINT "/* eslint-disable */" +#define DISABLE_TSLINT "/* tslint:disable */" + using namespace TC_NAMESPACE; class CodeGenerator @@ -74,10 +77,13 @@ public: _bServer(false), _bRecursive(false), _bUseSpecialPath(false), - _bUseStringRepresent(false), + _iLongType(Number), _bStringBinaryEncoding(false), + _bEnumReverseMappings(false), _bMinimalMembers(false), - _bDTS(false) {} + _bTS(false), + _bDTS(false), + _iOptimizeLevel(O0) {} void createFile(const string &file, const bool bEntry = true); @@ -95,16 +101,26 @@ public: void setUseSpecialPath(bool bEnable) { _bUseSpecialPath = bEnable; } - void setUseStringRepresent(bool bEnable) { _bUseStringRepresent = bEnable; } + void setLongType(int iLongType) { _iLongType = iLongType; } void setStringBinaryEncoding(bool bEnable) { _bStringBinaryEncoding = bEnable; } + void setEnumReverseMappings(bool bEnable) { _bEnumReverseMappings = bEnable; } + void setMinimalMembers(bool bEnable) { _bMinimalMembers = bEnable; } - void setDependent(set & deps) { _depMembers = deps; } + void setDependent(set& deps) { _depMembers = deps; } + + void setEnableTS(bool bEnable) { _bTS = bEnable; } void setEnableDTS(bool bEnable) { _bDTS = bEnable; } + void setOptimize(int iLevel) { _iOptimizeLevel = iLevel; } + + enum OPTIMIZE_LEVEL {O0 = 0, Os}; + + enum LONG_TYPE {Number = 0, String, BigInt}; + private: struct ImportFileType { @@ -132,29 +148,43 @@ private: string makeName(); - string findName(const string & sNamespace, const string & sName); + string findName(const string & sNamespace, const string & sName, const bool &bBase = false); private: string toFunctionName(const TypeIdPtr & pPtr, const string &sAction); - string getDataType(const TypePtr & pPtr); + string getDataType(const TypePtr& pPtr, const bool &bCastEnumAsAny = false); - string getDtsType(const TypePtr &pPtr, const bool bStream = true); + string getClassName(const TypePtr& pPtr); - string getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string & sNamespace); + string getTsType(const TypePtr &pPtr, const bool bStream = true, const bool bBase = false); - string getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string & sNamespace, const bool bGlobal); + string getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string & sNamespace, const bool &bGlobal = true, const bool &bCastEnumAsAny = false); - string generateJS(const StructPtr & pPtr, const string &sNamespace, bool &bNeedAssert); +private: + string generateJS(const StructPtr &pPtr, const string &sNamespace, bool &bNeedAssert, bool &bQuickFunc); string generateJS(const ConstPtr &pPtr, const string &sNamespace, bool &bNeedStream); string generateJS(const EnumPtr &pPtr, const string &sNamespace); - string generateJS(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedAssert); + string generateJS(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedAssert, bool &bQuickFunc); bool generateJS(const ContextPtr &pPtr); +private: + string generateTS(const StructPtr &pPtr, const string &sNamespace, bool &bNeedAssert, bool &bQuickFunc); + + string generateTS(const ConstPtr &pPtr, const string &sNamespace, bool &bNeedStream); + + string generateTS(const EnumPtr &pPtr, const string &sNamespace); + + string generateTS(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedAssert, bool &bQuickFunc); + + string generateTS(const NamespacePtr &pPtr, const string &sContent); + + void generateTS(const ContextPtr &cPtr); + private: string generateJSProxy(const NamespacePtr &nPtr, bool &bNeedRpc, bool &bNeedStream); @@ -164,6 +194,15 @@ private: bool generateJSProxy(const ContextPtr &pPtr); +private: + string generateTSProxy(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedRpc); + + string generateTSProxy(const NamespacePtr &nPtr, const InterfacePtr &pPtr); + + string generateTSProxy(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr); + + bool generateTSProxy(const ContextPtr &pPtr); + private: string generateJSServer(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedRpc, bool &bNeedAssert); @@ -179,6 +218,17 @@ private: bool generateJSServer(const ContextPtr &pPtr); +private: + string generateTSServerAsync(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr); + + string generateTSServerDispatch(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr); + + string generateTSServer(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedRpc, bool &bNeedAssert); + + string generateTSServer(const InterfacePtr &pPtr, const NamespacePtr &nPtr); + + bool generateTSServer(const ContextPtr &pPtr); + private: string generateJSServerImp(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr); @@ -188,6 +238,9 @@ private: void generateJSServerImp(const ContextPtr &cPtr); +private: + void generateTSServerImp(const ContextPtr &cPtr); + private: string generateDTS(const StructPtr &pPtr, const string &sNamespace); @@ -222,7 +275,7 @@ private: bool isBinBuffer(const TypePtr & pPtr) const; - bool isRawOrString(const TypePtr & pPtr) const; + string representArgument(const TypePtr& pPtr) const; bool isDependent(const string & sNamespace, const string & sName) const; @@ -245,17 +298,23 @@ private: bool _bUseSpecialPath; - bool _bUseStringRepresent; + int _iLongType; bool _bStringBinaryEncoding; + bool _bEnumReverseMappings; + bool _bMinimalMembers; bool _bEntry; string _sIdlFile; + bool _bTS; + bool _bDTS; + + int _iOptimizeLevel; }; #endif \ No newline at end of file diff --git a/tools/tars2node/file_util.cpp b/tools/tars2node/file_util.cpp index cd824a376d11ace19635970a370570e24a78a784..607662c2ec1ab27e2c2a91703bf489ea61570719 100644 --- a/tools/tars2node/file_util.cpp +++ b/tools/tars2node/file_util.cpp @@ -18,13 +18,14 @@ void CodeGenerator::makeUTF8File(const string& sFileName, const string& sFileContent) { - char header[3] = {(char)(0xef), (char)(0xbb), (char)(0xbf)}; + try { + string sData = TC_Encoder::gbk2utf8(sFileContent); - string sData(header, 3); - - sData += TC_Encoder::gbk2utf8(sFileContent); - - TC_File::save2file(sFileName, sData.c_str()); + TC_File::save2file(sFileName, sData.c_str()); + } catch (...) { + cout << "Convert GBK to UTF8 failed, current encoding is GBK."; + TC_File::save2file(sFileName, sFileContent.c_str()); + } } string CodeGenerator::getRealFileInfo(const string& sPath) diff --git a/tools/tars2node/gen_js.cpp b/tools/tars2node/gen_js.cpp index ae9a12f22a7fe9a41c71b56e4ad98869c3513c08..18477541fd1f49419ac5b2a593f797d4ef26927e 100644 --- a/tools/tars2node/gen_js.cpp +++ b/tools/tars2node/gen_js.cpp @@ -19,33 +19,61 @@ string CodeGenerator::generateJS(const EnumPtr &pPtr, const string &sNamespace) { ostringstream s; - s << TAB << sNamespace << "." << pPtr->getId() << " = {" << endl; - INC_TAB; - - //成员变量 - int nenum = -1; bool bDependent = false; - vector& member = pPtr->getAllMemberPtr(); - for (size_t i = 0; i < member.size(); i++) + + if (_bEnumReverseMappings) { - bDependent |= isDependent(sNamespace, member[i]->getId()); - - if (member[i]->hasDefault()) - { - nenum = TC_Common::strto(member[i]->def()); - } - else - { - nenum++; - } - - s << TAB << "\"" << member[i]->getId() << "\" : " << TC_Common::tostr(nenum) << "," << endl; + s << TAB << "(function(" << pPtr->getId() << ") {" << endl; + INC_TAB; + + int nenum = -1; + vector& member = pPtr->getAllMemberPtr(); + for (size_t i = 0; i < member.size(); i++) + { + bDependent |= isDependent(sNamespace, member[i]->getId()); + + if (member[i]->hasDefault()) + { + nenum = TC_Common::strto(member[i]->def()); + } + else + { + nenum++; + } + + s << TAB << pPtr->getId() << "[" << pPtr->getId() << "[\"" << member[i]->getId() << "\"] = " << TC_Common::tostr(nenum) << "] = " + << "\"" << member[i]->getId() << "\";" << endl; + } + DEL_TAB; + s << TAB << "}(" << sNamespace << "." << pPtr->getId() << " = {}));" << endl; } - s << TAB << "\"_classname\" : \"" << sNamespace << "." << pPtr->getId() << "\"" << endl; - DEL_TAB; - s << TAB << "};" << endl; + else + { + s << TAB << sNamespace << "." << pPtr->getId() << " = {" << endl; + INC_TAB; + + int nenum = -1; + vector& member = pPtr->getAllMemberPtr(); + for (size_t i = 0; i < member.size(); i++) + { + bDependent |= isDependent(sNamespace, member[i]->getId()); - //函数 + if (member[i]->hasDefault()) + { + nenum = TC_Common::strto(member[i]->def()); + } + else + { + nenum++; + } + + s << TAB << "\"" << member[i]->getId() << "\" : " << TC_Common::tostr(nenum) << (i < member.size() - 1 ? "," : "") << endl; + } + DEL_TAB; + s << TAB << "};" << endl; + } + + s << TAB << sNamespace << "." << pPtr->getId() << "._classname = \"" << sNamespace << "." << pPtr->getId() << "\";" << endl; s << TAB << sNamespace << "." << pPtr->getId() << "._write = function(os, tag, val) { return os.writeInt32(tag, val); };" << endl; s << TAB << sNamespace << "." << pPtr->getId() << "._read = function(is, tag, def) { return is.readInt32(tag, true, def); };" << endl; @@ -75,7 +103,7 @@ string CodeGenerator::generateJS(const ConstPtr &pPtr, const string &sNamespace, return s.str(); } -string CodeGenerator::generateJS(const StructPtr & pPtr, const string &sNamespace, bool &bNeedAssert) +string CodeGenerator::generateJS(const StructPtr &pPtr, const string &sNamespace, bool &bNeedAssert, bool &bQuickFunc) { if (_bMinimalMembers && !_bEntry && !isDependent(sNamespace, pPtr->getId())) { @@ -110,7 +138,7 @@ string CodeGenerator::generateJS(const StructPtr & pPtr, const string &sNamespac //_readFrom s << TAB << sNamespace << "." << pPtr->getId() << "._readFrom = function (is) {" << endl; INC_TAB; - s << TAB << "var tmp = new " << sNamespace << "." << pPtr->getId() << "();" << endl; + s << TAB << "var tmp = new " << sNamespace << "." << pPtr->getId() << ";" << endl; for (size_t i = 0; i < member.size(); i++) { string sFuncName = toFunctionName(member[i], "read"); @@ -120,7 +148,7 @@ string CodeGenerator::generateJS(const StructPtr & pPtr, const string &sNamespac if (isSimple(member[i]->getTypePtr())) { s << getDefault(member[i], member[i]->def(), sNamespace) - << (isRawOrString(member[i]->getTypePtr()) ? ", 1" : ""); + << representArgument(member[i]->getTypePtr()); } else { @@ -142,11 +170,21 @@ string CodeGenerator::generateJS(const StructPtr & pPtr, const string &sNamespac string sFuncName = toFunctionName(member[i], "write"); s << TAB << "os." << sFuncName << "(" << member[i]->getTag() << ", this." << member[i]->getId() - << (isRawOrString(member[i]->getTypePtr()) ? ", 1" : "") << ");" << endl; + << representArgument(member[i]->getTypePtr()) << ");" << endl; } DEL_TAB; s << TAB << "};" << endl; + /* + * Size Optimize: + * Remove support. + * Remove toBinBuffer, readFromObject, toObject, new, create members. + */ + if (_iOptimizeLevel == Os) + { + return s.str(); + } + //_equal vector key = pPtr->getKey(); @@ -233,19 +271,22 @@ string CodeGenerator::generateJS(const StructPtr & pPtr, const string &sNamespac DEL_TAB; s << TAB << "};" << endl; - //readFromJson + //readFromObject s << TAB << sNamespace << "." << pPtr->getId() << ".prototype.readFromObject = function(json) { "<< endl; INC_TAB; for (size_t i = 0; i < member.size(); i++) { if (isSimple(member[i]->getTypePtr())) { - s << TAB << "json.hasOwnProperty(\"" << member[i]->getId() << "\") && (this." << member[i]->getId() << " = json." << member[i]->getId() << ");" << endl; + s << TAB << "_hasOwnProperty.call(json, \"" << member[i]->getId() << "\") && (this." << member[i]->getId() << " = json." << member[i]->getId() << ");" << endl; } else { - s << TAB << "json.hasOwnProperty(\"" << member[i]->getId() << "\") && (this." << member[i]->getId() << ".readFromObject(json." << member[i]->getId() << "));" << endl; + s << TAB << "_hasOwnProperty.call(json, \"" << member[i]->getId() << "\") && (this." << member[i]->getId() << ".readFromObject(json." << member[i]->getId() << "));" << endl; } + bQuickFunc = true; } + s << TAB << "return this;" << endl; + DEL_TAB; s << TAB << "};" << endl; @@ -275,7 +316,7 @@ string CodeGenerator::generateJS(const StructPtr & pPtr, const string &sNamespac return s.str(); } -string CodeGenerator::generateJS(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedAssert) +string CodeGenerator::generateJS(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedAssert, bool &bQuickFunc) { ostringstream sstr; vector ss(pPtr->getAllStructPtr()); @@ -285,7 +326,7 @@ string CodeGenerator::generateJS(const NamespacePtr &pPtr, bool &bNeedStream, bo for (vector::iterator iter=ss.begin(); iter!=ss.end();) { - string str = generateJS(*iter, pPtr->getId(), bNeedAssert); + string str = generateJS(*iter, pPtr->getId(), bNeedAssert, bQuickFunc); if (!str.empty()) { sstr << str << endl; @@ -301,23 +342,31 @@ string CodeGenerator::generateJS(const NamespacePtr &pPtr, bool &bNeedStream, bo vector &cs = pPtr->getAllConstPtr(); for (size_t i = 0; i < cs.size(); i++) { - cstr << generateJS(cs[i], pPtr->getId(), bNeedStream); + string str = generateJS(cs[i], pPtr->getId(), bNeedStream); + + if (!str.empty()) { + cstr << str << endl; + } } ostringstream estr; vector & es = pPtr->getAllEnumPtr(); for (size_t i = 0; i < es.size(); i++) { - estr << generateJS(es[i], pPtr->getId()); + string str = generateJS(es[i], pPtr->getId()); + + if (!str.empty()) { + estr << str << endl; + } } ostringstream str; - if (!estr.str().empty()) str << estr.str() << endl; - if (!cstr.str().empty()) str << cstr.str() << endl; + if (!estr.str().empty()) str << estr.str(); + if (!cstr.str().empty()) str << cstr.str(); if (!sstr.str().empty()) { bNeedStream = true; - str << sstr.str() << endl; + str << sstr.str(); } return str.str(); @@ -340,20 +389,21 @@ bool CodeGenerator::generateJS(const ContextPtr &pPtr) } } - //先生成编解码体 + // generate encoders and decoders ostringstream estr; bool bNeedAssert = false; bool bNeedStream = false; + bool bQuickFunc = false; for(size_t i = 0; i < namespaces.size(); i++) { - estr << generateJS(namespaces[i], bNeedStream, bNeedAssert); + estr << generateJS(namespaces[i], bNeedStream, bNeedAssert, bQuickFunc); } if (estr.str().empty()) { return false; } - //再生成导入模块 + // generate module imports ostringstream ostr; for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) { @@ -364,9 +414,11 @@ bool CodeGenerator::generateJS(const ContextPtr &pPtr) ostr << "var " << it->second.sModule << " = require(\"" << it->second.sFile << "\");" << endl; } - //生成文件内容 + // concat generated code ostringstream sstr; sstr << printHeaderRemark("Structure"); + sstr << DISABLE_ESLINT << endl; + sstr << endl; sstr << "\"use strict\";" << endl << endl; if (bNeedAssert) { @@ -376,6 +428,11 @@ bool CodeGenerator::generateJS(const ContextPtr &pPtr) { sstr << "var " << IDL_NAMESPACE_STR << "Stream = require(\"" << _sStreamPath << "\");" << endl; } + if (bQuickFunc) + { + sstr << endl; + sstr << "var _hasOwnProperty = Object.prototype.hasOwnProperty;" << endl; + } sstr << ostr.str() << endl; sstr << istr.str(); sstr << estr.str() << endl; diff --git a/tools/tars2node/gen_js_dts.cpp b/tools/tars2node/gen_js_dts.cpp index ee66a0ec2e34207a5534999fd5263f1d9d03b80d..d7e99bef9152b2755ce05bda223397f34e90ef30 100644 --- a/tools/tars2node/gen_js_dts.cpp +++ b/tools/tars2node/gen_js_dts.cpp @@ -21,10 +21,9 @@ string CodeGenerator::generateDTS(const EnumPtr &pPtr, const string &sNamespace) ostringstream s; INC_TAB; - s << TAB << "enum " << pPtr->getId() << " {" << endl; + s << TAB << (_bEnumReverseMappings ? "enum " : "const enum ") << pPtr->getId() << " {" << endl; INC_TAB; - //成员变量 int nenum = -1; bool bDependent = false; vector& member = pPtr->getAllMemberPtr(); @@ -39,7 +38,7 @@ string CodeGenerator::generateDTS(const EnumPtr &pPtr, const string &sNamespace) { nenum++; } - s << TAB << "\"" << member[i]->getId() << "\" = " << TC_Common::tostr(nenum) << ((i < member.size() - 1) ? "," : "") << endl; + s << TAB << member[i]->getId() << " = " << TC_Common::tostr(nenum) << ((i < member.size() - 1) ? "," : "") << endl; } DEL_TAB; @@ -67,8 +66,8 @@ string CodeGenerator::generateDTS(const ConstPtr &pPtr, const string &sNamespace } INC_TAB; - s << TAB << "const " << pPtr->getTypeIdPtr()->getId() << ":" - << getDtsType(pPtr->getTypeIdPtr()->getTypePtr()) << ";" + s << TAB << "const " << pPtr->getTypeIdPtr()->getId() << ":" + << getTsType(pPtr->getTypeIdPtr()->getTypePtr()) << ";" << endl; DEL_TAB; return s.str(); @@ -81,51 +80,61 @@ string CodeGenerator::generateDTS(const StructPtr &pPtr, const string &sNamespac return ""; } - string sStructName = pPtr->getId() + "$OBJ"; vector &member = pPtr->getAllMemberPtr(); - ostringstream s; - INC_TAB; + + + ostringstream s; s << TAB << "class " << pPtr->getId() << " {" << endl; INC_TAB; - + for (size_t i = 0; i < member.size(); i++) { - s << TAB << (member[i]->getId()) << (member[i]->isRequire()?": ":"?: ") << getDtsType(member[i]->getTypePtr()) << ";" << endl; + s << TAB << (member[i]->getId()) << ": " << getTsType(member[i]->getTypePtr()) << ";" << endl; } if (member.size() > 0) { s << endl; } - s << TAB << "toObject(): " << sStructName << ";" << endl; - s << TAB << "readFromObject(json: " << sStructName << "): void;" << endl; - s << TAB << "toBinBuffer(): " << IDL_NAMESPACE_STR << "Stream.BinBuffer;" << endl; - s << TAB << "static new(): " << pPtr->getId() << ";" << endl; - s << TAB << "static create(is: " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "InputStream): " << pPtr->getId() << ";" << endl; + /* + * Size Optimize: + * Remove support. + * Remove toBinBuffer, readFromObject, toObject, new, create members. + */ + if (_iOptimizeLevel != Os) + { + s << TAB << "toObject(): " << pPtr->getId() << ".Object;" << endl; + s << TAB << "readFromObject(json: " << pPtr->getId() << ".Object): " << pPtr->getId() << ";" << endl; + s << TAB << "toBinBuffer(): " << IDL_NAMESPACE_STR << "Stream.BinBuffer;" << endl; + s << TAB << "static new(): " << pPtr->getId() << ";" << endl; + s << TAB << "static create(is: " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "InputStream): " << pPtr->getId() << ";" << endl; + } DEL_TAB; - s << TAB << "}" << endl; + s << TAB << "}" << endl << endl; - s << TAB << "interface " << sStructName << " {" << endl; + s << TAB << "namespace " << pPtr->getId() << " {" << endl; + INC_TAB; + s << TAB << "interface Object {" << endl; INC_TAB; - for (size_t i = 0; i < member.size(); i++) { - const string &sType = getDtsType(member[i]->getTypePtr(), false); - if (!sType.empty()) - { - s << TAB << (member[i]->getId()) << (member[i]->isRequire()?": ":"?: ") << sType << ";" << endl; - } + const string &sType = getTsType(member[i]->getTypePtr(), false); + s << TAB << (member[i]->getId()) << (member[i]->isRequire() ? ": " : "?: ") << (!sType.empty() ? sType : "never") << ";" << endl; } DEL_TAB; s << TAB << "}" << endl; DEL_TAB; + s << TAB << "}" << endl; + + DEL_TAB; + return s.str(); } string CodeGenerator::generateDTS(const NamespacePtr &pPtr, bool &bNeedStream) { - //结构 + // struct ostringstream sstr; vector ss(pPtr->getAllStructPtr()); for (size_t last = 0; last != ss.size() && ss.size() != 0;) @@ -134,19 +143,19 @@ string CodeGenerator::generateDTS(const NamespacePtr &pPtr, bool &bNeedStream) for (vector::iterator iter=ss.begin(); iter!=ss.end();) { string str = generateDTS(*iter, pPtr->getId()); - if (!str.empty()) + if (!str.empty()) { sstr << str << endl; iter = ss.erase(iter); - } - else + } + else { iter++; } } } - //常量 + // const ostringstream cstr; vector &cs = pPtr->getAllConstPtr(); for (size_t i = 0; i < cs.size(); i++) @@ -154,7 +163,7 @@ string CodeGenerator::generateDTS(const NamespacePtr &pPtr, bool &bNeedStream) cstr << generateDTS(cs[i], pPtr->getId(), bNeedStream); } - //枚举 + // enum ostringstream estr; vector &es = pPtr->getAllEnumPtr(); for (size_t i = 0; i < es.size(); i++) @@ -179,7 +188,7 @@ string CodeGenerator::generateDTS(const NamespacePtr &pPtr, const string &sConte ostringstream str; if (!sContent.empty()) { - str << "export declare namespace " << pPtr->getId() << " {" << endl; + str << "export namespace " << pPtr->getId() << " {" << endl; str << sContent; str << "}" << endl << endl; } @@ -189,8 +198,8 @@ string CodeGenerator::generateDTS(const NamespacePtr &pPtr, const string &sConte void CodeGenerator::generateDTS(const ContextPtr &pPtr) { vector namespaces = pPtr->getNamespaces(); - - //先生成编解码体 + + // generate encoders and decoders ostringstream estr; bool bNeedStream = false; for (size_t i = 0; i < namespaces.size(); i++) @@ -202,7 +211,7 @@ void CodeGenerator::generateDTS(const ContextPtr &pPtr) return; } - //再生成导入模块 + // generate module imports ostringstream ostr; if (bNeedStream) { @@ -212,15 +221,18 @@ void CodeGenerator::generateDTS(const ContextPtr &pPtr) for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) { if (it->second.sModule.empty()) continue; - + if (estr.str().find(it->second.sModule + ".") == string::npos) continue; ostr << "import * as " << it->second.sModule << " from \"" << TC_File::excludeFileExt(it->second.sFile) << "\";" << endl; } - //生成文件内容 + // concat generated code ostringstream sstr; sstr << printHeaderRemark("Structure"); + sstr << DISABLE_TSLINT << endl; + sstr << DISABLE_ESLINT << endl; + sstr << endl; sstr << ostr.str() << endl; sstr << estr.str() << endl; diff --git a/tools/tars2node/gen_proxy.cpp b/tools/tars2node/gen_proxy.cpp index 4db48601aaa23c9679130986cdb1044c8eb9912a..698f5fe98b7c7d8ae77133e3a06ede6d18b4ae37 100644 --- a/tools/tars2node/gen_proxy.cpp +++ b/tools/tars2node/gen_proxy.cpp @@ -16,6 +16,15 @@ #include "code_generator.h" +#define INVOKE_RETURN(protocol, prefix, params) \ + str << TAB << "return this._worker." << TC_Common::lower(protocol) << "_invoke(\"" << oPtr->getId() << "\", "; \ + str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$" << prefix << "E"; \ + str << "(" << sParams << params << "), arguments[arguments.length - 1], "; \ + str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$IF" << ").then("; \ + str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$" << prefix << "D, "; \ + str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$ER);" << endl; +#define PROTOCOL_PARAMS (sParams.empty() ? "" : ", ") << "version" + struct SortOperation { bool operator()(const OperationPtr &o1, const OperationPtr &o2) @@ -28,9 +37,10 @@ string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, const InterfaceP { ostringstream str; - //SETP01 生成编码接口 - str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$EN = function ("; vector & vParamDecl = oPtr->getAllParamDeclPtr(); + bool bHasParamOut = false; + string sParams = ""; + for (size_t i = 0; i < vParamDecl.size(); i++) { if (vParamDecl[i]->isOut()) @@ -38,9 +48,48 @@ string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, const InterfaceP continue; } - str << (i == 0?"":", ") << vParamDecl[i]->getTypeIdPtr()->getId(); + sParams += (sParams.empty()?"":", ") + vParamDecl[i]->getTypeIdPtr()->getId(); + } + + // generate function metadata (SharedFunctionInfo) + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$IF = {" << endl; + + INC_TAB; + + str << TAB << "\"name\" : \"" << oPtr->getId() << "\"," << endl; + str << TAB << "\"return\" : \"" << getClassName(oPtr->getReturnPtr()->getTypePtr()) << "\"," << endl; + str << TAB << "\"arguments\" : ["; + for (size_t i = 0; i < vParamDecl.size(); i++) + { + str << (i > 0 ? ", {" : "{") << endl; + + INC_TAB; + + str << TAB << "\"name\" : \"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\"," << endl; + str << TAB << "\"class\" : \"" << getClassName(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << "\"," << endl; + + if (vParamDecl[i]->isOut()) + { + bHasParamOut = true; + str << TAB << "\"direction\" : \"out\"" << endl; + } + else + { + str << TAB << "\"direction\" : \"in\"" << endl; + } + + DEL_TAB; + + str << TAB << "}"; } - str << ") {" << endl; + str << "]" << endl; + + DEL_TAB; + + str << TAB << "};" << endl << endl; + + // generate IDL Encoder ($IE) + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$IE = function (" << sParams << ") {" << endl; INC_TAB; @@ -51,10 +100,10 @@ string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, const InterfaceP if (vParamDecl[i]->isOut()) continue; str << TAB << "os." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(" - << (i + 1) << ", " << vParamDecl[i]->getTypeIdPtr()->getId() - << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl; + << (i + 1) << ", " << vParamDecl[i]->getTypeIdPtr()->getId() + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ");" << endl; - // 写入 Dependent 列表 + // push the symbol into dependent list getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); } @@ -64,14 +113,13 @@ string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, const InterfaceP str << TAB << "};" << endl << endl; - - //STEP02 生成解码函数 - str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$DE = function (data) {" << endl; + // generate IDL Decoder ($ID) + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$ID = function (data) {" << endl; INC_TAB; str << TAB << "try {" << endl; INC_TAB; - bool bHasParamOut = false; +// bool bHasParamOut = false; if (vParamDecl.size() > 0) { for (size_t i = 0; i < vParamDecl.size(); i++) @@ -104,7 +152,7 @@ string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, const InterfaceP if (isSimple(oPtr->getReturnPtr()->getTypePtr())) { str << getDefault(oPtr->getReturnPtr(), oPtr->getReturnPtr()->def(), nPtr->getId()) - << (isRawOrString(oPtr->getReturnPtr()->getTypePtr()) ? ", 1" : ""); + << representArgument(oPtr->getReturnPtr()->getTypePtr()); } else { @@ -130,8 +178,8 @@ string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, const InterfaceP if (isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) { - str << getDefault(vParamDecl[i]->getTypeIdPtr(), vParamDecl[i]->getTypeIdPtr()->def(), nPtr->getId()) - << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : ""); + str << getDefault(vParamDecl[i]->getTypeIdPtr(), vParamDecl[i]->getTypeIdPtr()->def(), nPtr->getId()) + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); } else { @@ -163,80 +211,155 @@ string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, const InterfaceP DEL_TAB; str << TAB << "} catch (e) {" << endl; INC_TAB; - str << TAB << "throw {" << endl; - INC_TAB; - str << TAB << "\"request\" : data.request," << endl; - str << TAB << "\"response\" : {" << endl; - INC_TAB; - str << TAB << "\"costtime\" : data.request.costtime," << endl; - str << TAB << "\"error\" : {" << endl; - INC_TAB; - str << TAB << "\"code\" : " << IDL_NAMESPACE_STR << "Error.CLIENT.DECODE_ERROR," << endl; - str << TAB << "\"message\" : e.message" << endl; - DEL_TAB; - str << TAB << "}" << endl; - DEL_TAB; - str << TAB << "}" << endl; - DEL_TAB; - str << TAB << "};" << endl; + str << TAB << "throw _makeError(data, e.message, " << IDL_NAMESPACE_STR << "Error.CLIENT.DECODE_ERROR);" << endl; DEL_TAB; str << TAB << "}" << endl; DEL_TAB; str << TAB << "};" << endl << endl; + // generate Protocol Encoder ($PE) + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$PE = function (" + << sParams << (sParams.empty() ? "" : ", ") << "__$PROTOCOL$VERSION) {" << endl; + + INC_TAB; + + str << TAB << "var " << PROTOCOL_VAR << " = new " << IDL_NAMESPACE_STR << "Stream.UniAttribute();" << endl; - //STEP03 生成框架调用错误处理函数 - str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$ER = function (data) {" << endl; + str << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = __$PROTOCOL$VERSION;" << endl; + + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (vParamDecl[i]->isOut()) continue; + + str << TAB << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(\"" + << vParamDecl[i]->getTypeIdPtr()->getId() << "\", " << vParamDecl[i]->getTypeIdPtr()->getId() + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ");" << endl; + + // push the symbol into dependent list + getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); + } + + str << TAB << "return " << PROTOCOL_VAR << ";" << endl; + DEL_TAB; + str << TAB << "};" << endl << endl; + + // generate Protocol Decoder ($PD) + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$PD = function (data) {" << endl; + INC_TAB; + str << TAB << "try {" << endl; INC_TAB; - str << TAB << "throw {" << endl; + if (oPtr->getReturnPtr()->getTypePtr() || bHasParamOut) { + str << TAB << "var " << PROTOCOL_VAR << " = data.response." << PROTOCOL_VAR << ";" << endl; + } + str << TAB << "return {" << endl; INC_TAB; str << TAB << "\"request\" : data.request," << endl; str << TAB << "\"response\" : {" << endl; INC_TAB; - str << TAB << "\"costtime\" : data.request.costtime," << endl; - str << TAB << "\"error\" : data.error" << endl; + str << TAB << "\"costtime\" : data.request.costtime"; + + if (oPtr->getReturnPtr()->getTypePtr()) + { + str << "," << endl; + str << TAB << "\"return\" : " << PROTOCOL_VAR << "." << toFunctionName(oPtr->getReturnPtr(), "read") << "(\"\""; + + if (!isSimple(oPtr->getReturnPtr()->getTypePtr()) && !isBinBuffer(oPtr->getReturnPtr()->getTypePtr())) + { + str << ", " << getDataType(oPtr->getReturnPtr()->getTypePtr()); + } + + str << ", " << getDefault(oPtr->getReturnPtr(), "", nPtr->getId(), true) + << representArgument(oPtr->getReturnPtr()->getTypePtr()); + + str << ")"; + } + + if (bHasParamOut) + { + str << "," << endl; + str << TAB << "\"arguments\" : {" << endl; + + INC_TAB; + + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (!vParamDecl[i]->isOut()) continue; + + str << TAB << "\"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\" : " + << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "read") + << "(\"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\""; + + if (!isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) && !isBinBuffer(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) + { + str << ", " << getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); + } + + str << ")"; + + if (i == vParamDecl.size() - 1) + { + str << endl; + } + else + { + str << "," << endl; + } + + } + + DEL_TAB; + str << TAB << "}"; + } + + str << endl; DEL_TAB; str << TAB << "}" << endl; DEL_TAB; + str << TAB << "};" << endl; + DEL_TAB; + str << TAB << "} catch (e) {" << endl; + INC_TAB; + str << TAB << "throw _makeError(data, e.message, " << IDL_NAMESPACE_STR << "Error.CLIENT.DECODE_ERROR);" << endl; + DEL_TAB; str << TAB << "}" << endl; DEL_TAB; str << TAB << "};" << endl << endl; - //SETP04 生成函数接口 - str << TAB << nPtr->getId() << "." << pPtr->getId() << "Proxy.prototype." << oPtr->getId() << " = function ("; - for (size_t i = 0; i < vParamDecl.size(); i++) - { - if (vParamDecl[i]->isOut()) - { - continue; - } + // generate error handler ($ER) + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$ER = function (data) {" << endl; + INC_TAB; + str << TAB << "throw _makeError(data, \"Call " << pPtr->getId() << "::" << oPtr->getId() << " failed\");" << endl; + DEL_TAB; + str << TAB << "};" << endl << endl; - str << (i == 0?"":", ") << vParamDecl[i]->getTypeIdPtr()->getId(); - } - str << ") {" << endl; + + // generate function body + str << TAB << nPtr->getId() << "." << pPtr->getId() << "Proxy.prototype." << oPtr->getId() << " = function (" + << sParams << ") {" << endl; INC_TAB; - str << TAB << "return this._worker." << TC_Common::lower(IDL_NAMESPACE_STR) << "_invoke(\"" << oPtr->getId() << "\", "; - str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$EN("; - for (size_t i = 0; i < vParamDecl.size(); i++) - { - if (vParamDecl[i]->isOut()) - { - continue; - } + str << TAB << "var version = this._worker.version;" << endl; - str << (i == 0?"":", ") << vParamDecl[i]->getTypeIdPtr()->getId(); - } - str << "), arguments[arguments.length - 1]).then("; - str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$DE, "; - str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$ER);" << endl; + str << TAB << "if (version === " << PROTOCOL_SIMPLE << " || version === " << PROTOCOL_COMPLEX << ") {" << endl; + INC_TAB; + INVOKE_RETURN(PROTOCOL_VAR, "P", PROTOCOL_PARAMS); + DEL_TAB; + str << TAB << "} else {" << endl; + INC_TAB; + INVOKE_RETURN(IDL_NAMESPACE_STR, "I", ""); + DEL_TAB; + str << TAB << "}" << endl; DEL_TAB; str << TAB << "};" << endl; + // add the function into the prototype of the proxy class + str << TAB << nPtr->getId() << "." << pPtr->getId() << "Proxy." << oPtr->getId() << " = " + << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$IF;" << endl; + return str.str(); } @@ -303,8 +426,8 @@ bool CodeGenerator::generateJSProxy(const ContextPtr &cPtr) istr << TAB << namespaces[i]->getId() << "." << is[ii]->getId() << "Proxy = function () {" << endl; INC_TAB; - istr << TAB << "this._name = undefined;" << endl; - istr << TAB << "this._worker = undefined;" << endl; + istr << TAB << "this._name = undefined;" << endl; + istr << TAB << "this._worker = undefined;" << endl; DEL_TAB; istr << TAB << "};" << endl << endl; @@ -319,16 +442,29 @@ bool CodeGenerator::generateJSProxy(const ContextPtr &cPtr) istr << TAB << "return this._worker.timeout;" << endl; DEL_TAB; istr << TAB << "};" << endl << endl; + + istr << TAB << namespaces[i]->getId() << "." << is[ii]->getId() << "Proxy.prototype.setVersion = function (iVersion) {" << endl; + INC_TAB; + istr << TAB << "this._worker.version = iVersion;" << endl; + DEL_TAB; + istr << TAB << "};" << endl << endl; + + istr << TAB << namespaces[i]->getId() << "." << is[ii]->getId() << "Proxy.prototype.getVersion = function () {" << endl; + INC_TAB; + istr << TAB << "return this._worker.version;" << endl; + DEL_TAB; + istr << TAB << "};" << endl; } } - //先生成编解码 + 代理类 + // generate proxy classes with encoders and decoders ostringstream estr; bool bNeedAssert = false; bool bNeedStream = false; + bool bQuickFunc = false; for(size_t i = 0; i < namespaces.size(); i++) { - estr << generateJS(namespaces[i], bNeedStream, bNeedAssert); + estr << generateJS(namespaces[i], bNeedStream, bNeedAssert, bQuickFunc); } bool bNeedRpc = false; @@ -342,7 +478,7 @@ bool CodeGenerator::generateJSProxy(const ContextPtr &cPtr) return false; } - //再生成导入模块 + // generate module imports ostringstream ostr; for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) { @@ -353,9 +489,11 @@ bool CodeGenerator::generateJSProxy(const ContextPtr &cPtr) ostr << "var " << it->second.sModule << " = require(\"" << it->second.sFile << "\");" << endl; } - //生成文件内容 + // concat generated code ostringstream sstr; sstr << printHeaderRemark("Client"); + sstr << DISABLE_ESLINT << endl; + sstr << endl; sstr << "\"use strict\";" << endl << endl; if (bNeedAssert) { @@ -371,6 +509,48 @@ bool CodeGenerator::generateJSProxy(const ContextPtr &cPtr) } sstr << ostr.str() << endl; + + // generate helper functions + if (bQuickFunc) + { + sstr << "var _hasOwnProperty = Object.prototype.hasOwnProperty;" << endl; + } + if (bNeedRpc) + { + sstr << TAB << "var _makeError = function (data, message, type) {" << endl; + INC_TAB; + sstr << TAB << "var error = new Error(message || \"\");" << endl; + sstr << TAB << "error.request = data.request;" << endl; + sstr << TAB << "error.response = {" << endl; + INC_TAB; + sstr << TAB << "\"costtime\" : data.request.costtime" << endl; + DEL_TAB; + sstr << TAB << "};" << endl; + sstr << TAB << "if (type === " << IDL_NAMESPACE_STR << "Error.CLIENT.DECODE_ERROR) {" << endl; + INC_TAB; + sstr << TAB << "error.name = \"DECODE_ERROR\";" << endl; + sstr << TAB << "error.response.error = {" << endl; + INC_TAB; + sstr << TAB << "\"code\" : type," << endl; + sstr << TAB << "\"message\" : message" << endl; + DEL_TAB; + sstr << TAB << "};" << endl; + DEL_TAB; + sstr << TAB << "} else {" << endl; + INC_TAB; + sstr << TAB << "error.name = \"RPC_ERROR\";" << endl; + sstr << TAB << "error.response.error = data.error;" << endl; + DEL_TAB; + sstr << TAB << "}" << endl; + sstr << TAB << "return error;" << endl; + DEL_TAB; + sstr << TAB << "};" << endl; + } + if (bQuickFunc || bNeedRpc) + { + sstr << endl; + } + sstr << istr.str() << endl; sstr << estr.str() << endl; @@ -380,4 +560,7 @@ bool CodeGenerator::generateJSProxy(const ContextPtr &cPtr) makeUTF8File(sFileName, sstr.str()); return true; -} \ No newline at end of file +} + +#undef INVOKE_RETURN +#undef PROTOCOL_PARAMS \ No newline at end of file diff --git a/tools/tars2node/gen_proxy_dts.cpp b/tools/tars2node/gen_proxy_dts.cpp index f1c05ced17ce21931977be3f778346b1e53992d6..560de515390644387141b210e3cf2df42253da15 100644 --- a/tools/tars2node/gen_proxy_dts.cpp +++ b/tools/tars2node/gen_proxy_dts.cpp @@ -25,79 +25,55 @@ string CodeGenerator::generateDTSProxy(const InterfacePtr &pPtr) INC_TAB; str << TAB << "class " << pPtr->getId() << "Proxy {" << endl; INC_TAB; - str << TAB << "setTimeout(timeout: number): void;" << endl; + str << TAB << "setTimeout(iTimeout: number): void;" << endl; str << TAB << "getTimeout(): number;" << endl; + str << TAB << "setVersion(iVersion: number): void;" << endl; + str << TAB << "getVersion(): number;" << endl; for (size_t i = 0; i < vOperation.size(); i++) { OperationPtr &oPtr = vOperation[i]; + string funcReturnGeneric = "<"; + if (oPtr->getReturnPtr()->getTypePtr()) + { + funcReturnGeneric += getTsType(oPtr->getReturnPtr()->getTypePtr()) + ", "; + } + else + { + funcReturnGeneric += "undefined, "; + } + str << TAB << oPtr->getId() << "("; + string argType = ""; vector &vParamDecl = oPtr->getAllParamDeclPtr(); - for (size_t j = 0; j < vParamDecl.size(); j++) + for (size_t j = 0; j < vParamDecl.size(); j++) { - if(vParamDecl[j]->isOut()) + if(vParamDecl[j]->isOut()) { + argType += (argType.empty() ? "" : ", ") + vParamDecl[j]->getTypeIdPtr()->getId() + ": " + getTsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()); continue; } - str << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getDtsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()); + str << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getTsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()); str << ", "; } - str << "property?: " << IDL_NAMESPACE_STR << "Rpc.InvokeProperty): Promise<" << pPtr->getId() << "$" << oPtr->getId() << "$DE>;" << endl; - } - DEL_TAB; - str << TAB << "}" << endl; - - //interface - for (size_t i = 0; i < vOperation.size(); i++) - { - OperationPtr &oPtr = vOperation[i]; - str << TAB << "interface " << pPtr->getId() << "$" << oPtr->getId() << "$DE {" << endl; - INC_TAB; - str << TAB << "request: object;" << endl; - str << TAB << "response: {" << endl; - INC_TAB; - str << TAB << "costtime: number;" << endl; - if (oPtr->getReturnPtr()->getTypePtr()) + if (!argType.empty()) { - str << TAB << "return: " << getDtsType(oPtr->getReturnPtr()->getTypePtr()) << ";" << endl; + funcReturnGeneric += "{ " + argType + " }>"; } else { - str << TAB << "return: void;" << endl; - } - - vector &vParamDecl = oPtr->getAllParamDeclPtr(); - bool hasArgs = false; - for (size_t j = 0; j < vParamDecl.size(); j++) - { - if(vParamDecl[j]->isOut()) { - hasArgs = true; - break; - } + funcReturnGeneric += "undefined>"; } - if(hasArgs) - { - str << TAB << "arguments: {" << endl; - INC_TAB; - for (size_t j = 0; j < vParamDecl.size(); j++) - { - if(!vParamDecl[j]->isOut()) { - continue; - } - str << TAB << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getDtsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()) << ";" << endl; - } - DEL_TAB; - str << TAB << "}" << endl; - } + str << "options?: " << IDL_NAMESPACE_STR << "Rpc.InvokeProperty): Promise<" << IDL_NAMESPACE_STR << "Rpc.ProxyResponse" << funcReturnGeneric << ">;" << endl; - DEL_TAB; - str << TAB << "}" << endl; - DEL_TAB; - str << TAB << "}" << endl; + str << TAB << "static " << oPtr->getId() << ": " << IDL_NAMESPACE_STR << "Rpc.SharedFunctionInfo" << ";" << endl; } + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; return str.str(); @@ -107,15 +83,15 @@ string CodeGenerator::generateDTSProxy(const NamespacePtr &nPtr, bool &bNeedStre { ostringstream str; vector &is = nPtr->getAllInterfacePtr(); - for (size_t i = 0; i < is.size(); i++) - { - str << generateDTSProxy(is[i]) << endl; - } - if (is.size() != 0) + if (is.size() > 0) { bNeedStream = true; bNeedRpc = true; } + for (size_t i = 0; i < is.size(); i++) + { + str << generateDTSProxy(is[i]) << endl; + } return str.str(); } @@ -123,7 +99,7 @@ void CodeGenerator::generateDTSProxy(const ContextPtr &cPtr) { vector namespaces = cPtr->getNamespaces(); - //先生成编解码 + 代理类 + // generate proxy classes with encoders and decoders ostringstream estr; bool bNeedStream = false; bool bNeedRpc = false; @@ -141,20 +117,23 @@ void CodeGenerator::generateDTSProxy(const ContextPtr &cPtr) return; } - //再生成导入模块 + // generate module imports ostringstream ostr; for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) { if (it->second.sModule.empty()) continue; - + if (estr.str().find(it->second.sModule + ".") == string::npos) continue; ostr << "import * as " << it->second.sModule << " from \"" << TC_File::excludeFileExt(it->second.sFile) << "\";" << endl; } - //生成文件内容 + // concat generated code ostringstream sstr; sstr << printHeaderRemark("Client"); + sstr << DISABLE_TSLINT << endl; + sstr << DISABLE_ESLINT << endl; + sstr << endl; if (bNeedStream) { sstr << "import * as " << IDL_NAMESPACE_STR << "Stream from \"" << _sStreamPath << "\";" << endl; diff --git a/tools/tars2node/gen_proxy_ts.cpp b/tools/tars2node/gen_proxy_ts.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a659b6dcadfb9a7e425a36575c86ae36016b8835 --- /dev/null +++ b/tools/tars2node/gen_proxy_ts.cpp @@ -0,0 +1,516 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT 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 "code_generator.h" + +#define INVOKE_RETURN(protocol, prefix, params) \ + str << TAB << "return this._worker." << TC_Common::lower(protocol) << "_invoke(\"" << oPtr->getId() << "\", "; \ + str << prefix << "." << TC_Common::lower(protocol) << "Encoder"; \ + str << "(" << sParams << params << "), options, " << prefix << ").then("; \ + str << prefix << "." << TC_Common::lower(protocol) << "Decoder, "; \ + str << prefix << ".errorResponser);" << endl; +#define PROTOCOL_PARAMS (sParams.empty() ? "" : ", ") << "version" + +struct SortOperation +{ + bool operator()(const OperationPtr &o1, const OperationPtr &o2) + { + return o1->getId() < o2->getId(); + } +}; + +string CodeGenerator::generateTSProxy(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr) +{ + ostringstream str; + + vector & vParamDecl = oPtr->getAllParamDeclPtr(); + bool bHasParamOut = false; + string sParams = ""; + string sParamsWithType = ""; + + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (vParamDecl[i]->isOut()) + { + continue; + } + + sParams += (sParams.empty() ? "" : ", ") + + vParamDecl[i]->getTypeIdPtr()->getId(); + + sParamsWithType += (sParamsWithType.empty() ? "" : ", ") + + vParamDecl[i]->getTypeIdPtr()->getId() + + ": " + + getTsType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); + } + + // generate function metadata (SharedFunctionInfo) + str << TAB << "static " << oPtr->getId() << " = _castFunctionInfo({" << endl; + INC_TAB; + + str << TAB << "name: \"" << oPtr->getId() << "\"," << endl; + str << TAB << "return: \"" << getClassName(oPtr->getReturnPtr()->getTypePtr()) << "\"," << endl; + str << TAB << "arguments: ["; + for (size_t i = 0; i < vParamDecl.size(); i++) + { + str << (i > 0 ? ", {" : "{") << endl; + INC_TAB; + + str << TAB << "name: \"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\"," << endl; + str << TAB << "class: \"" << getClassName(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << "\"," << endl; + + if (vParamDecl[i]->isOut()) + { + bHasParamOut = true; + str << TAB << "direction: \"out\"" << endl; + } + else + { + str << TAB << "direction: \"in\"" << endl; + } + + DEL_TAB; + str << TAB << "}"; + } + str << "]," << endl; + + // generate IDL Encoder ($IE) + str << TAB << TC_Common::lower(IDL_NAMESPACE_STR) << "Encoder(" << sParamsWithType << ") {" << endl; + INC_TAB; + + str << TAB << "const os = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "OutputStream();" << endl; + + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (vParamDecl[i]->isOut()) continue; + + str << TAB << "os." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(" + << (i + 1) << ", " << vParamDecl[i]->getTypeIdPtr()->getId() + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ");" << endl; + + // push the symbol into dependent list + getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); + } + + str << TAB << "return os.getBinBuffer();" << endl; + + DEL_TAB; + str << TAB << "}," << endl; + + // generate IDL Decoder ($ID) + str << TAB << TC_Common::lower(IDL_NAMESPACE_STR) << "Decoder(data: " << IDL_NAMESPACE_STR << "Rpc.RpcResponse) {" << endl; + INC_TAB; + + str << TAB << "try {" << endl; + INC_TAB; + + if (oPtr->getReturnPtr()->getTypePtr() || bHasParamOut) + { + str << TAB << "var is = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "InputStream(data.response.sBuffer);" << endl; + } + + str << TAB << "return {" << endl; + INC_TAB; + str << TAB << "request: data.request," << endl; + str << TAB << "response: {" << endl; + INC_TAB; + str << TAB << "costtime: data.request.costtime," << endl; + + str << TAB << "return: "; + if (oPtr->getReturnPtr()->getTypePtr()) + { + str << "is." << toFunctionName(oPtr->getReturnPtr(), "read") << "(0, true, "; + + if (isSimple(oPtr->getReturnPtr()->getTypePtr())) + { + str << getDefault(oPtr->getReturnPtr(), oPtr->getReturnPtr()->def(), nPtr->getId(), true, true) + << representArgument(oPtr->getReturnPtr()->getTypePtr()); + } + else + { + str << getDataType(oPtr->getReturnPtr()->getTypePtr(), true); + } + + str << ")," << endl; + } + else + { + str << "undefined as undefined," << endl; + } + + str << TAB << "arguments: "; + if (bHasParamOut) + { + str << "{" << endl; + INC_TAB; + + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (!vParamDecl[i]->isOut()) continue; + + str << TAB << vParamDecl[i]->getTypeIdPtr()->getId() + << ": is." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "read") << "(" << (i + 1) << ", true, "; + + if (isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) + { + str << getDefault(vParamDecl[i]->getTypeIdPtr(), vParamDecl[i]->getTypeIdPtr()->def(), nPtr->getId(), true, true) + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); + } + else + { + str << getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr(), true); + } + + str << ")"; + + if (i == vParamDecl.size() - 1) + { + str << endl; + } + else + { + str << "," << endl; + } + } + + DEL_TAB; + str << TAB << "}" << endl; + } + else + { + str << "undefined as undefined" << endl; + } + + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "};" << endl; + DEL_TAB; + str << TAB << "} catch (e) {" << endl; + INC_TAB; + str << TAB << "throw _makeError(data, e.message, " << IDL_NAMESPACE_STR << "Rpc.error.CLIENT.DECODE_ERROR);" << endl; + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "}," << endl; + + // generate Protocol Encoder ($PE) + str << TAB << TC_Common::lower(PROTOCOL_VAR) << "Encoder(" << sParamsWithType << (sParamsWithType.empty() ? "" : ", ") << "__$PROTOCOL$VERSION: number) {" << endl; + INC_TAB; + + str << TAB << "const " << PROTOCOL_VAR << " = new " << IDL_NAMESPACE_STR << "Stream.UniAttribute();" << endl; + + str << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = __$PROTOCOL$VERSION;" << endl; + + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (vParamDecl[i]->isOut()) continue; + + str << TAB << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(\"" + << vParamDecl[i]->getTypeIdPtr()->getId() << "\", " << vParamDecl[i]->getTypeIdPtr()->getId() + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ");" << endl; + + // push the symbol into dependent list + getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); + } + + str << TAB << "return " << PROTOCOL_VAR << ";" << endl; + DEL_TAB; + str << TAB << "}," << endl; + + // generate Protocol Decoder ($PD) + str << TAB << TC_Common::lower(PROTOCOL_VAR) << "Decoder(data: " << IDL_NAMESPACE_STR << "Rpc.RpcResponse) {" << endl; + INC_TAB; + + str << TAB << "try {" << endl; + INC_TAB; + if (oPtr->getReturnPtr()->getTypePtr() || bHasParamOut) { + str << TAB << "const " << PROTOCOL_VAR << ": " << IDL_NAMESPACE_STR << "Stream.UniAttribute = (data.response as any)." << PROTOCOL_VAR << ";" << endl; + } + str << TAB << "return {" << endl; + INC_TAB; + str << TAB << "request: data.request," << endl; + str << TAB << "response: {" << endl; + INC_TAB; + str << TAB << "costtime: data.request.costtime," << endl; + + str << TAB << "return: "; + if (oPtr->getReturnPtr()->getTypePtr()) + { + str << PROTOCOL_VAR << "." << toFunctionName(oPtr->getReturnPtr(), "read") << "(\"\""; + + if (!isSimple(oPtr->getReturnPtr()->getTypePtr()) && !isBinBuffer(oPtr->getReturnPtr()->getTypePtr())) + { + str << ", " << getDataType(oPtr->getReturnPtr()->getTypePtr(), true); + } + + str << ", " << getDefault(oPtr->getReturnPtr(), "", nPtr->getId(), true, true) + << representArgument(oPtr->getReturnPtr()->getTypePtr()); + + str << ")," << endl; + } + else + { + str << "undefined as undefined," << endl; + } + + str << TAB << "arguments: "; + if (bHasParamOut) + { + str << "{" << endl; + INC_TAB; + + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (!vParamDecl[i]->isOut()) continue; + + str << TAB << vParamDecl[i]->getTypeIdPtr()->getId() << ": " + << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "read") + << "(\"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\""; + + if (!isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) && !isBinBuffer(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) + { + str << ", " << getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr(), true); + } + + str << ")"; + + if (i == vParamDecl.size() - 1) + { + str << endl; + } + else + { + str << "," << endl; + } + } + + DEL_TAB; + str << TAB << "}" << endl; + } + else + { + str << "undefined as undefined" << endl; + } + + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "};" << endl; + DEL_TAB; + str << TAB << "} catch (e) {" << endl; + INC_TAB; + str << TAB << "throw _makeError(data, e.message, " << IDL_NAMESPACE_STR << "Rpc.error.CLIENT.DECODE_ERROR);" << endl; + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "}," << endl; + + // generate error handler ($ER) + str << TAB << "errorResponser(data: " << IDL_NAMESPACE_STR << "Rpc.RpcResponse) {" << endl; + INC_TAB; + str << TAB << "throw _makeError(data, \"Call " << pPtr->getId() << "::" << oPtr->getId() << " failed\");" << endl; + DEL_TAB; + str << TAB << "}" << endl; + + DEL_TAB; + str << TAB << "})" << endl << endl; // end of metadata + + // generate function body + str << TAB << oPtr->getId() << "(" << sParamsWithType << (sParamsWithType.empty() ? "" : ", ") << "options?: " << IDL_NAMESPACE_STR << "Rpc.InvokeProperty) {" << endl; + INC_TAB; + + string sFuncFullName = pPtr->getId() + "Proxy." + oPtr->getId(); + str << TAB << "const version = this._worker.version;" << endl; + + str << TAB << "if (version === " << PROTOCOL_SIMPLE << " || version === " << PROTOCOL_COMPLEX << ") {" << endl; + INC_TAB; + INVOKE_RETURN(PROTOCOL_VAR, sFuncFullName, PROTOCOL_PARAMS); + DEL_TAB; + str << TAB << "} else {" << endl; + INC_TAB; + INVOKE_RETURN(IDL_NAMESPACE_STR, sFuncFullName, ""); + DEL_TAB; + str << TAB << "}" << endl; + + DEL_TAB; + str << TAB << "}" << endl << endl; + + return str.str(); +} + +string CodeGenerator::generateTSProxy(const NamespacePtr &nPtr, const InterfacePtr &pPtr) +{ + ostringstream str; + + vector & vOperation = pPtr->getAllOperationPtr(); + sort(vOperation.begin(), vOperation.end(), SortOperation()); + for (size_t i = 0; i < vOperation.size(); i++) + { + str << generateTSProxy(nPtr, pPtr, vOperation[i]); + } + + return str.str(); +} + +string CodeGenerator::generateTSProxy(const NamespacePtr &nPtr, bool &bNeedStream, bool &bNeedRpc) +{ + ostringstream str; + vector &is = nPtr->getAllInterfacePtr(); + if (is.size() > 0) + { + bNeedStream = true; + bNeedRpc = true; + } + + for (size_t i = 0; i < is.size(); i++) + { + str << TAB << "export class " << is[i]->getId() << "Proxy {" << endl; + INC_TAB; + + str << TAB << "protected _name!: string" << endl; + str << TAB << "protected _worker!: " << IDL_NAMESPACE_STR << "Rpc.ObjectProxy" << endl << endl; + + str << TAB << "setTimeout (iTimeout: number) { this._worker.timeout = iTimeout; }" << endl; + str << TAB << "getTimeout () { return this._worker.timeout; }" << endl; + str << TAB << "setVersion (iVersion: number) { this._worker.version = iVersion; }" << endl; + str << TAB << "getVersion () { return this._worker.version; }" << endl << endl; + + str << generateTSProxy(nPtr, is[i]) << endl; + + DEL_TAB; + str << TAB << "}" << endl << endl; + } + + return str.str(); +} + +bool CodeGenerator::generateTSProxy(const ContextPtr &cPtr) +{ + vector namespaces = cPtr->getNamespaces(); + + // generate proxy classes with encoders and decoders + ostringstream estr; + bool bNeedStream = false; + bool bNeedRpc = false; + bool bNeedAssert = false; + bool bQuickFunc = false; + for(size_t i = 0; i < namespaces.size(); i++) + { + ostringstream kstr; + + kstr << generateTS(namespaces[i], bNeedStream, bNeedAssert, bQuickFunc); + + INC_TAB; + kstr << generateTSProxy(namespaces[i], bNeedStream, bNeedRpc); + DEL_TAB; + + estr << generateTS(namespaces[i], kstr.str()); + } + if (estr.str().empty()) + { + return false; + } + + // generate module imports + ostringstream sstr; + sstr << printHeaderRemark("Client"); + sstr << DISABLE_TSLINT << endl; + sstr << DISABLE_ESLINT << endl; + sstr << endl; + sstr << "/// " << endl; + if (bNeedAssert) + { + sstr << TAB << "import assert = require(\"assert\");" << endl; + } + if (bNeedStream) + { + sstr << "import * as " << IDL_NAMESPACE_STR << "Stream from \"" << _sStreamPath << "\";" << endl; + } + if (bNeedRpc) + { + sstr << "import * as " << IDL_NAMESPACE_STR << "Rpc from \"" << _sRpcPath << "\";" << endl; + } + + for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) + { + if (it->second.sModule.empty()) continue; + + if (estr.str().find(it->second.sModule + ".") == string::npos) continue; + + sstr << "import * as " << it->second.sModule << " from \"" << TC_File::excludeFileExt(it->second.sFile) << "\";" << endl; + } + + // generate helper functions + if (bQuickFunc || bNeedRpc) + { + sstr << endl; + } + if (bQuickFunc) + { + sstr << "const _hasOwnProperty = Object.prototype.hasOwnProperty;" << endl; + } + if (bNeedRpc) + { + sstr << TAB << "function _castFunctionInfo(data: SharedFunctionInfo) { return data; }" << endl; + sstr << TAB << "function _makeError(data: " << IDL_NAMESPACE_STR << "Rpc.RpcResponse, message: string, type?: number): " << IDL_NAMESPACE_STR << "Rpc.RpcError {" << endl; + INC_TAB; + sstr << TAB << "var error: any = new Error(message || \"\");" << endl; + sstr << TAB << "error.request = data.request;" << endl; + sstr << TAB << "error.response = {" << endl; + INC_TAB; + sstr << TAB << "costtime: data.request.costtime" << endl; + DEL_TAB; + sstr << TAB << "};" << endl; + sstr << TAB << "if (type === " << IDL_NAMESPACE_STR << "Rpc.error.CLIENT.DECODE_ERROR) {" << endl; + INC_TAB; + sstr << TAB << "error.name = \"DECODE_ERROR\";" << endl; + sstr << TAB << "error.response.error = {" << endl; + INC_TAB; + sstr << TAB << "code: type," << endl; + sstr << TAB << "message: message" << endl; + DEL_TAB; + sstr << TAB << "};" << endl; + DEL_TAB; + sstr << TAB << "} else {" << endl; + INC_TAB; + sstr << TAB << "error.name = \"RPC_ERROR\";" << endl; + sstr << TAB << "error.response.error = data.error;" << endl; + DEL_TAB; + sstr << TAB << "}" << endl; + sstr << TAB << "return error;" << endl; + DEL_TAB; + sstr << TAB << "}" << endl << endl; + + sstr << "export interface SharedFunctionInfo extends " << IDL_NAMESPACE_STR << "Rpc.SharedFunctionInfo {" << endl; + INC_TAB; + sstr << TAB << TC_Common::lower(IDL_NAMESPACE_STR) << "Encoder (...args: any[]): " << IDL_NAMESPACE_STR << "Stream.BinBuffer," << endl; + sstr << TAB << TC_Common::lower(IDL_NAMESPACE_STR) << "Decoder (data: " << IDL_NAMESPACE_STR << "Rpc.RpcResponse): " << IDL_NAMESPACE_STR << "Rpc.ProxyResponse," << endl; + sstr << TAB << TC_Common::lower(PROTOCOL_VAR) << "Encoder (...args: any[]): " << IDL_NAMESPACE_STR << "Stream.UniAttribute," << endl; + sstr << TAB << TC_Common::lower(PROTOCOL_VAR) << "Decoder (data: " << IDL_NAMESPACE_STR << "Rpc.RpcResponse): " << IDL_NAMESPACE_STR << "Rpc.ProxyResponse," << endl; + sstr << TAB << "errorResponser (data: " << IDL_NAMESPACE_STR << "Rpc.RpcResponse): never" << endl; + DEL_TAB; + sstr << TAB << "}" << endl << endl; + } + + sstr << estr.str() << endl; + + string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(cPtr->getFileName())) + "Proxy.ts"; + TC_File::makeDirRecursive(_sToPath); + makeUTF8File(sFileName, sstr.str()); + + return true; +} diff --git a/tools/tars2node/gen_server.cpp b/tools/tars2node/gen_server.cpp index ffe241fc0724e1e0d6124bb4a3c5e4d2402560ca..6825787d53758dbe93c25382116b9249bd26dd24 100644 --- a/tools/tars2node/gen_server.cpp +++ b/tools/tars2node/gen_server.cpp @@ -58,7 +58,7 @@ string CodeGenerator::generateAsync(const NamespacePtr &nPtr, const InterfacePtr { sParams += "_ret"; - // 写入 Dependent 列表 + // push the symbol into dependent list getDataType(oPtr->getReturnPtr()->getTypePtr()); } @@ -89,8 +89,8 @@ string CodeGenerator::generateAsync(const NamespacePtr &nPtr, const InterfacePtr str << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = this.getRequestVersion();" << endl; if (oPtr->getReturnPtr()->getTypePtr()) { - str << TAB << PROTOCOL_VAR << "." << toFunctionName(oPtr->getReturnPtr(), "write") << "(\"\", _ret" - << (isRawOrString(oPtr->getReturnPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl; + str << TAB << PROTOCOL_VAR << "." << toFunctionName(oPtr->getReturnPtr(), "write") << "(\"\", _ret" + << representArgument(oPtr->getReturnPtr()->getTypePtr()) << ");" << endl; } for (size_t i = 0; i < vParamDecl.size(); i++) { @@ -98,7 +98,7 @@ string CodeGenerator::generateAsync(const NamespacePtr &nPtr, const InterfacePtr str << TAB << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(\"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\", " << vParamDecl[i]->getTypeIdPtr()->getId() - << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl; + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ");" << endl; } str << endl; str << TAB << "this.doResponse(" << PROTOCOL_VAR << ".encode());" << endl; @@ -109,8 +109,8 @@ string CodeGenerator::generateAsync(const NamespacePtr &nPtr, const InterfacePtr str << TAB << "var os = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "OutputStream();" << endl; if (oPtr->getReturnPtr()->getTypePtr()) { - str << TAB << "os." << toFunctionName(oPtr->getReturnPtr(), "write") << "(0, _ret" - << (isRawOrString(oPtr->getReturnPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl; + str << TAB << "os." << toFunctionName(oPtr->getReturnPtr(), "write") << "(0, _ret" + << representArgument(oPtr->getReturnPtr()->getTypePtr()) << ");" << endl; } for (size_t i = 0; i < vParamDecl.size(); i++) { @@ -118,7 +118,7 @@ string CodeGenerator::generateAsync(const NamespacePtr &nPtr, const InterfacePtr str << TAB << "os." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(" << (i + 1) << ", " << vParamDecl[i]->getTypeIdPtr()->getId() - << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl; + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ");" << endl; } str << endl; str << TAB << "this.doResponse(os.getBinBuffer());" << endl; @@ -172,7 +172,7 @@ string CodeGenerator::generateDispatch(const NamespacePtr &nPtr, const Interface if (vParamDecl[i]->isOut()) { dstr << ", " << getDefault(vParamDecl[i]->getTypeIdPtr(), "", nPtr->getId(), true) - << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : ""); + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); } dstr << ");" << endl; @@ -194,7 +194,7 @@ string CodeGenerator::generateDispatch(const NamespacePtr &nPtr, const Interface if (isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) { dstr << getDefault(vParamDecl[i]->getTypeIdPtr(), vParamDecl[i]->getTypeIdPtr()->def(), nPtr->getId()) - << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : ""); + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); } else { @@ -243,7 +243,7 @@ string CodeGenerator::generateJSServer(const InterfacePtr &pPtr, const Namespace ostringstream str; vector & vOperation = pPtr->getAllOperationPtr(); - //生成类 + // generate the implementation class str << TAB << nPtr->getId() << "." << pPtr->getId() << "Imp = function () { " << endl; INC_TAB; str << TAB << "this._name = undefined;" << endl; @@ -251,10 +251,10 @@ string CodeGenerator::generateJSServer(const InterfacePtr &pPtr, const Namespace DEL_TAB; str << TAB << "};" << endl << endl; - //生成初始化函数 + // generate the initialize function str << TAB << nPtr->getId() << "." << pPtr->getId() << "Imp.prototype.initialize = function () {};" << endl << endl; - //生成分发函数 + // generate the dispatch function str << TAB << nPtr->getId() << "." << pPtr->getId() << "Imp.prototype.onDispatch = function (current, funcName, binBuffer) { " << endl; INC_TAB; str << TAB << "if (\"__\" + funcName in this) {" << endl; @@ -269,10 +269,10 @@ string CodeGenerator::generateJSServer(const InterfacePtr &pPtr, const Namespace DEL_TAB; str << TAB << "};" << endl << endl; - //生成 PING 方法 + // generate the ping function str << generatePing(nPtr, pPtr) << endl; - //生成接口函数 + // generate functions for (size_t i = 0; i < vOperation.size(); i++) { str << generateJSServer(nPtr, pPtr, vOperation[i]) << endl; @@ -321,13 +321,14 @@ bool CodeGenerator::generateJSServer(const ContextPtr &pPtr) } } - //生成编解码 + 服务类 + // generate server classes with encoders and decoders ostringstream estr; bool bNeedAssert = false; bool bNeedStream = false; + bool bQuickFunc = false; for(size_t i = 0; i < namespaces.size(); i++) { - estr << generateJS(namespaces[i], bNeedStream, bNeedAssert); + estr << generateJS(namespaces[i], bNeedStream, bNeedAssert, bQuickFunc); } bool bNeedRpc = false; @@ -341,7 +342,7 @@ bool CodeGenerator::generateJSServer(const ContextPtr &pPtr) return false; } - //再生成导入模块 + // generate module imports ostringstream ostr; if (bNeedAssert) { @@ -363,10 +364,17 @@ bool CodeGenerator::generateJSServer(const ContextPtr &pPtr) ostr << TAB << "var " << it->second.sModule << " = require(\"" << it->second.sFile << "\");" << endl; } + if (bQuickFunc) + { + ostr << endl; + ostr << TAB << "var _hasOwnProperty = Object.prototype.hasOwnProperty;" << endl; + } ostringstream str; str << printHeaderRemark("Server"); + str << DISABLE_ESLINT << endl; + str << endl; str << "\"use strict\";" << endl << endl; str << ostr.str() << endl; str << istr.str(); diff --git a/tools/tars2node/gen_server_dts.cpp b/tools/tars2node/gen_server_dts.cpp index 064713f009fb2b5eeffbae00430d809e58d18fa7..07c1698de33b26d4ae94db9cb40886d513966233 100644 --- a/tools/tars2node/gen_server_dts.cpp +++ b/tools/tars2node/gen_server_dts.cpp @@ -25,34 +25,37 @@ string CodeGenerator::generateDTSServer(const NamespacePtr &nPtr, const Interfac INC_TAB; str << TAB << "class " << pPtr->getId() << "Imp {" << endl; INC_TAB; - str << TAB << "initialize(): Promise | void;" << endl; + str << TAB << "initialize(): PromiseLike | void;" << endl; str << TAB << "protected onDispatch(current: " << IDL_NAMESPACE_STR << "Rpc." << IDL_TYPE << "Current, funcName: string, binBuffer: " << IDL_NAMESPACE_STR << "Stream.BinBuffer): number" << endl; for (size_t i = 0; i < vOperation.size(); i++) { OperationPtr &oPtr = vOperation[i]; - str << TAB << oPtr->getId() << "(current: " << pPtr->getId() << "$" << oPtr->getId() << "$CUR"; + str << TAB << oPtr->getId() << "(current: " << pPtr->getId() << "Imp." << oPtr->getId() << "Current"; vector &vParamDecl = oPtr->getAllParamDeclPtr(); - for (size_t j = 0; j < vParamDecl.size(); j++) + for (size_t j = 0; j < vParamDecl.size(); j++) { - str << ", " << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getDtsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()); + str << ", " << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getTsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()); } - str << "): void;" << endl; + str << "): any;" << endl; } DEL_TAB; str << TAB << "}" << endl; - //interface + // Additional namespace + str << TAB << "namespace " << pPtr->getId() << "Imp {" << endl; + INC_TAB; + for (size_t i = 0; i < vOperation.size(); i++) { OperationPtr &oPtr = vOperation[i]; - str << TAB << "interface " << pPtr->getId() << "$" << oPtr->getId() << "$CUR extends " << IDL_NAMESPACE_STR << "Rpc." << IDL_TYPE << "Current {" <getId() << "Current extends " << IDL_NAMESPACE_STR << "Rpc." << IDL_TYPE << "Current {" <getReturnPtr()->getTypePtr()) { - str << "sendResponse(ret: " << getDtsType(oPtr->getReturnPtr()->getTypePtr()); + str << "sendResponse(ret: " << getTsType(oPtr->getReturnPtr()->getTypePtr()); vector &vParamDecl = oPtr->getAllParamDeclPtr(); for (size_t j = 0; j < vParamDecl.size(); j++) @@ -60,7 +63,7 @@ string CodeGenerator::generateDTSServer(const NamespacePtr &nPtr, const Interfac if(!vParamDecl[j]->isOut()) { continue; } - str << ", " << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getDtsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()) ; + str << ", " << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getTsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()) ; } str << "): void;" << endl; } @@ -72,8 +75,11 @@ string CodeGenerator::generateDTSServer(const NamespacePtr &nPtr, const Interfac DEL_TAB; str << TAB << "}" << endl; } + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; return str.str(); } @@ -100,7 +106,7 @@ void CodeGenerator::generateDTSServer(const ContextPtr &pPtr) { vector namespaces = pPtr->getNamespaces(); - //生成编解码 + 服务类 + // generate server classes with encoders and decoders ostringstream estr; bool bNeedStream = false; bool bNeedRpc = false; @@ -110,7 +116,7 @@ void CodeGenerator::generateDTSServer(const ContextPtr &pPtr) kstr << generateDTS(namespaces[i], bNeedStream); kstr << generateDTSServer(namespaces[i], bNeedStream, bNeedRpc); - + estr << generateDTS(namespaces[i], kstr.str()); } if(estr.str().empty()) @@ -118,7 +124,7 @@ void CodeGenerator::generateDTSServer(const ContextPtr &pPtr) return; } - //再生成导入模块 + // generate module imports ostringstream ostr; if (bNeedStream) { @@ -131,7 +137,7 @@ void CodeGenerator::generateDTSServer(const ContextPtr &pPtr) for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) { if (it->second.sModule.empty()) continue; - + if (estr.str().find(it->second.sModule + ".") == string::npos) continue; ostr << "import * as " << it->second.sModule << " from \"" << TC_File::excludeFileExt(it->second.sFile) << "\";" << endl; @@ -139,6 +145,9 @@ void CodeGenerator::generateDTSServer(const ContextPtr &pPtr) ostringstream str; str << printHeaderRemark("Server"); + str << DISABLE_TSLINT << endl; + str << DISABLE_ESLINT << endl; + str << endl; str << ostr.str() << endl; str << estr.str() << endl; diff --git a/tools/tars2node/gen_server_ts.cpp b/tools/tars2node/gen_server_ts.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bd37611ab7b8308d3d54b70637861a9572e903a0 --- /dev/null +++ b/tools/tars2node/gen_server_ts.cpp @@ -0,0 +1,404 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT 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 "code_generator.h" + +string CodeGenerator::generateTSServerAsync(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr) +{ + ostringstream str; + + string sParams = ""; + if (oPtr->getReturnPtr()->getTypePtr()) + { + sParams += "_ret: " + getTsType(oPtr->getReturnPtr()->getTypePtr()); + + // push the symbol into dependent list + getDataType(oPtr->getReturnPtr()->getTypePtr()); + } + + vector & vParamDecl = oPtr->getAllParamDeclPtr(); + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (!vParamDecl[i]->isOut()) continue; + + sParams += (sParams.empty() ? "": ", ") + vParamDecl[i]->getTypeIdPtr()->getId(); + sParams += ": " + getTsType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); + } + + str << TAB << "protected static __" << oPtr->getId() << "_responser(this: " << IDL_NAMESPACE_STR << "Rpc.TarsCurrent, " << sParams << ") {" << endl; + + INC_TAB; + + if (sParams.empty()) + { + str << TAB << "this.doResponse(new " << IDL_NAMESPACE_STR << "Stream.BinBuffer());" << endl; + DEL_TAB; + str << TAB << "}" << endl; + + return str.str(); + } + + str << TAB << "if (this.getRequestVersion() === " << PROTOCOL_SIMPLE << " || this.getRequestVersion() === " << PROTOCOL_COMPLEX << ") {" << endl; + INC_TAB; + str << TAB << "const " << PROTOCOL_VAR << " = new " << IDL_NAMESPACE_STR << "Stream.UniAttribute();" << endl; + str << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = this.getRequestVersion();" << endl; + if (oPtr->getReturnPtr()->getTypePtr()) + { + str << TAB << PROTOCOL_VAR << "." << toFunctionName(oPtr->getReturnPtr(), "write") << "(\"\", _ret" + << representArgument(oPtr->getReturnPtr()->getTypePtr()) << ");" << endl; + } + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (!vParamDecl[i]->isOut()) continue; + + str << TAB << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(\"" + << vParamDecl[i]->getTypeIdPtr()->getId() << "\", " << vParamDecl[i]->getTypeIdPtr()->getId() + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ");" << endl; + } + str << endl; + str << TAB << "this.doResponse(" << PROTOCOL_VAR << ".encode());" << endl; + DEL_TAB; + str << TAB << "} else {" << endl; + + INC_TAB; + str << TAB << "const os = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "OutputStream();" << endl; + if (oPtr->getReturnPtr()->getTypePtr()) + { + str << TAB << "os." << toFunctionName(oPtr->getReturnPtr(), "write") << "(0, _ret" + << representArgument(oPtr->getReturnPtr()->getTypePtr()) << ");" << endl; + } + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (!vParamDecl[i]->isOut()) continue; + + str << TAB << "os." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(" + << (i + 1) << ", " << vParamDecl[i]->getTypeIdPtr()->getId() + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ");" << endl; + } + str << endl; + str << TAB << "this.doResponse(os.getBinBuffer());" << endl; + DEL_TAB; + str << TAB << "}" << endl; + + DEL_TAB; + + str << TAB << "}" << endl; + + return str.str(); +} + +string CodeGenerator::generateTSServerDispatch(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr) +{ + ostringstream str; + vector & vParamDecl = oPtr->getAllParamDeclPtr(); + + str << TAB << "protected __" << oPtr->getId() << "(current: " << IDL_NAMESPACE_STR << "Rpc.TarsCurrent"; + if (vParamDecl.size() != 0) str << ", binBuffer: " << IDL_NAMESPACE_STR << "Stream.BinBuffer"; + str << ") {" << endl; + + INC_TAB; + + ostringstream dstr; + + for (size_t i = 0; i < vParamDecl.size(); i++) + { + dstr << TAB << "let " << vParamDecl[i]->getTypeIdPtr()->getId() << ": " << getTsType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ";" << endl; + } + if (vParamDecl.size() != 0) + { + dstr << endl; + } + + dstr << TAB << "if (current.getRequestVersion() === " << PROTOCOL_SIMPLE << " || current.getRequestVersion() === " << PROTOCOL_COMPLEX << ") {" << endl; + INC_TAB; + dstr << TAB << "const " << PROTOCOL_VAR << " = new " << IDL_NAMESPACE_STR << "Stream.UniAttribute();" << endl; + dstr << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = current.getRequestVersion();" << endl; + dstr << TAB << PROTOCOL_VAR << ".decode(binBuffer);" << endl; + + for (size_t i = 0; i < vParamDecl.size(); i++) + { + dstr << TAB << vParamDecl[i]->getTypeIdPtr()->getId() + << " = " << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "read") + << "(\"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\""; + + if (!isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) && !isBinBuffer(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) + { + dstr << ", " << getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr(), true); + } + + if (vParamDecl[i]->isOut()) + { + dstr << ", " << getDefault(vParamDecl[i]->getTypeIdPtr(), "", nPtr->getId(), true, true) + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); + } + + dstr << ");" << endl; + } + DEL_TAB; + dstr << TAB << "} else {" << endl; + + INC_TAB; + dstr << TAB << "const is = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "InputStream(binBuffer);" << endl; + string sParams = ""; + for (size_t i = 0; i < vParamDecl.size(); i++) + { + sParams += ", " + vParamDecl[i]->getTypeIdPtr()->getId(); + + dstr << TAB << vParamDecl[i]->getTypeIdPtr()->getId() + << " = is." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "read") << "(" + << (i + 1) << ", " << (vParamDecl[i]->isOut() ? "false" : "true") << ", "; + + if (isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) + { + dstr << getDefault(vParamDecl[i]->getTypeIdPtr(), vParamDecl[i]->getTypeIdPtr()->def(), nPtr->getId(), true, true) + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); + } + else + { + dstr << getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr(), true); + } + + dstr << ");" << endl; + } + DEL_TAB; + dstr << TAB << "}" << endl << endl; + + if (!sParams.empty()) + { + str << dstr.str(); + } + + str << TAB << "current.sendResponse = " << pPtr->getId() << "Imp.__" << oPtr->getId() << "_responser;" << endl << endl; + + str << TAB << "this." << oPtr->getId() << "(current" << sParams << ");" << endl << endl; + + str << TAB << "return " << IDL_NAMESPACE_STR << "Rpc.error.SUCCESS;" << endl; + + DEL_TAB; + + str << TAB << "}" << endl; + + return str.str(); +} + +string CodeGenerator::generateTSServer(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedRpc, bool &bNeedAssert) +{ + ostringstream str; + + vector & is = pPtr->getAllInterfacePtr(); + for (size_t i = 0; i < is.size(); i++) + { + str << generateTSServer(is[i], pPtr) << endl; + } + if (is.size() != 0) + { + bNeedRpc = true; + bNeedStream = true; + bNeedAssert = true; + } + + return str.str(); +} + +string CodeGenerator::generateTSServer(const InterfacePtr &pPtr, const NamespacePtr &nPtr) +{ + ostringstream str; + vector & vOperation = pPtr->getAllOperationPtr(); + + // generate the implementation class + str << TAB << "export abstract class " << pPtr->getId() << "Imp { " << endl; + INC_TAB; + str << TAB << "_name!: string" << endl; + str << TAB << "_worker!: any" << endl << endl; + + // generate the initialize function + str << TAB << "initialize(): PromiseLike | void {}" << endl << endl; + + // generate the dispatch function + str << TAB << "onDispatch(current: " << IDL_NAMESPACE_STR << "Rpc.TarsCurrent, funcName: string, binBuffer: " << IDL_NAMESPACE_STR << "Stream.BinBuffer) { " << endl; + INC_TAB; + str << TAB << "if (\"__\" + funcName in this) {" << endl; + INC_TAB; + str << TAB << "return (this as any)[\"__\" + funcName](current, binBuffer);" << endl; + DEL_TAB; + str << TAB << "} else {" << endl; + INC_TAB; + str << TAB << "return " << IDL_NAMESPACE_STR << "Rpc.error.SERVER.FUNC_NOT_FOUND;" << endl; + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "}" << endl << endl; + + // generate the ping function + str << TAB << "__" << TC_Common::lower(IDL_NAMESPACE_STR) << "_ping(current: " << IDL_NAMESPACE_STR << "Rpc.TarsCurrent) { " << endl; + INC_TAB; + str << TAB << "const _ret = 0;" << endl; + str << TAB << "if (current.getRequestVersion() === " << PROTOCOL_SIMPLE << " || current.getRequestVersion() === " << PROTOCOL_COMPLEX << ") {" << endl; + INC_TAB; + str << TAB << "const " << PROTOCOL_VAR << " = new " << IDL_NAMESPACE_STR << "Stream.UniAttribute();" << endl; + str << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = current.getRequestVersion();" << endl; + str << TAB << PROTOCOL_VAR << ".writeInt32(\"\", _ret);" << endl << endl; + str << TAB << "current.doResponse(" << PROTOCOL_VAR << ".encode());" << endl; + DEL_TAB; + str << TAB << "} else {" << endl; + INC_TAB; + str << TAB << "const os = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "OutputStream();" << endl; + str << TAB << "os.writeInt32(0, _ret);" << endl << endl; + str << TAB << "current.doResponse(os.getBinBuffer());" << endl; + DEL_TAB; + str << TAB << "}" << endl << endl; + str << TAB << "return " << IDL_NAMESPACE_STR << "Rpc.error.SUCCESS;" << endl; + DEL_TAB; + str << TAB << "}" << endl << endl; + + // generate functions + for (size_t i = 0; i < vOperation.size(); i++) + { + const OperationPtr &oPtr = vOperation[i]; + + // generate function definition + str << TAB << oPtr->getId() << "(current: " << pPtr->getId() << "Imp." << oPtr->getId() << "Current"; + + vector &vParamDecl = oPtr->getAllParamDeclPtr(); + for (size_t j = 0; j < vParamDecl.size(); j++) + { + str << ", " << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getTsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()); + } + str << "): any { " << endl; + + INC_TAB; + str << TAB << "assert.fail(\"" << oPtr->getId() << " function not implemented\");" << endl; + DEL_TAB; + str << TAB << "}" << endl << endl; + + // generate encoder and decoder + str << generateTSServerAsync(nPtr, pPtr, vOperation[i]) << endl; + str << generateTSServerDispatch(nPtr, pPtr, vOperation[i]) << endl; + } + + DEL_TAB; + str << TAB << "}" << endl << endl; // end of class + + // generate additional namespaces + str << TAB << "export namespace " << pPtr->getId() << "Imp {" << endl; + INC_TAB; + + for (size_t i = 0; i < vOperation.size(); i++) + { + OperationPtr &oPtr = vOperation[i]; + + str << TAB << "export interface " << oPtr->getId() << "Current extends " << IDL_NAMESPACE_STR << "Rpc." << IDL_TYPE << "Current {" <getReturnPtr()->getTypePtr()) + { + str << "sendResponse(ret: " << getTsType(oPtr->getReturnPtr()->getTypePtr()); + + vector &vParamDecl = oPtr->getAllParamDeclPtr(); + for (size_t j = 0; j < vParamDecl.size(); j++) + { + if(!vParamDecl[j]->isOut()) { + continue; + } + str << ", " << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getTsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()) ; + } + str << "): void;" << endl; + } + else + { + str << "sendResponse(): void;" << endl; + } + + DEL_TAB; + str << TAB << "}" << endl; + } + + DEL_TAB; + str << TAB << "}" << endl; + + return str.str(); +} + +bool CodeGenerator::generateTSServer(const ContextPtr &pPtr) +{ + vector namespaces = pPtr->getNamespaces(); + + // generate server classes with encoders and decoders + ostringstream estr; + bool bNeedStream = false; + bool bNeedRpc = false; + bool bNeedAssert = false; + bool bQuickFunc = false; + for(size_t i = 0; i < namespaces.size(); i++) + { + ostringstream kstr; + kstr << generateTS(namespaces[i], bNeedStream, bNeedAssert, bQuickFunc); + + INC_TAB; + kstr << generateTSServer(namespaces[i], bNeedStream, bNeedRpc, bNeedAssert); + DEL_TAB; + + estr << generateTS(namespaces[i], kstr.str()); + } + if (estr.str().empty()) + { + return false; + } + + ostringstream str; + + // generate the source file + str << printHeaderRemark("Server"); + str << DISABLE_TSLINT << endl; + str << DISABLE_ESLINT << endl; + str << endl; + str << "/// " << endl; + if (bNeedAssert) + { + str << TAB << "import assert = require(\"assert\");" << endl; + } + if (bNeedStream) + { + str << "import * as " << IDL_NAMESPACE_STR << "Stream from \"" << _sStreamPath << "\";" << endl; + } + if (bNeedRpc) + { + str << "import * as " << IDL_NAMESPACE_STR << "Rpc from \"" << _sRpcPath << "\";" << endl; + } + + for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) + { + if (it->second.sModule.empty()) continue; + + if (estr.str().find(it->second.sModule + ".") == string::npos) continue; + + str << "import * as " << it->second.sModule << " from \"" << TC_File::excludeFileExt(it->second.sFile) << "\";" << endl; + } + if (bQuickFunc) + { + str << endl; + str << TAB << "const _hasOwnProperty = Object.prototype.hasOwnProperty;" << endl; + } + + str << endl << estr.str() << endl; + + string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(pPtr->getFileName())) + ".ts"; + + TC_File::makeDirRecursive(_sToPath); + makeUTF8File(sFileName, str.str()); + + return true; +} diff --git a/tools/tars2node/gen_server_ts_imp.cpp b/tools/tars2node/gen_server_ts_imp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6de85a68740650def594370ba02ae562658dfbd4 --- /dev/null +++ b/tools/tars2node/gen_server_ts_imp.cpp @@ -0,0 +1,110 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT 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 "code_generator.h" + +void CodeGenerator::generateTSServerImp(const ContextPtr &cPtr) +{ + string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(cPtr->getFileName())) + "Imp.ts"; + if (TC_File::isFileExist(sFileName)) + { + return ; + } + + ostringstream str; + str << printHeaderRemark("Imp"); + + vector namespaces = cPtr->getNamespaces(); + + // generate the server implementation class + ostringstream estr; + set setInterface; + for(size_t i = 0; i < namespaces.size(); i++) + { + estr << "export namespace " << namespaces[i]->getId() << " {" << endl; + INC_TAB; + + vector & is = namespaces[i]->getAllInterfacePtr(); + for (size_t ii = 0; ii < is.size(); ii++) + { + if (setInterface.count(namespaces[i]->getId() + "::" + is[ii]->getId()) != 0) + { + continue; + } + setInterface.insert(namespaces[i]->getId() + "::" + is[ii]->getId()); + + estr << TAB << "export class " << is[ii]->getId() << "Imp extends base." << namespaces[i]->getId() << "." << is[ii]->getId() << "Imp { " << endl; + INC_TAB; + + estr << TAB << "initialize() {" << endl; + INC_TAB; + estr << TAB << "// TODO: implement initialize" << endl; + DEL_TAB; + estr << TAB << "}" << endl << endl; + + vector & vOperation = is[ii]->getAllOperationPtr(); + for (size_t iii = 0; iii < vOperation.size(); iii++) + { + const OperationPtr &oPtr = vOperation[iii]; + + // generate function entries + estr << TAB << oPtr->getId() << "(current: base." << namespaces[i]->getId() << "." << is[ii]->getId() << "Imp." << oPtr->getId() << "Current"; + + vector &vParamDecl = oPtr->getAllParamDeclPtr(); + for (size_t j = 0; j < vParamDecl.size(); j++) + { + estr << ", " << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getTsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr(), true, true); + } + estr << ") { " << endl; + + INC_TAB; + estr << TAB << "// TODO: implement " << oPtr->getId() << "" << endl; + + DEL_TAB; + estr << TAB << "}" << endl; + if (iii != vOperation.size() - 1) estr << endl; + } + + DEL_TAB; + estr << TAB << "}" << endl; + if (ii != is.size() - 1) estr << endl; + } + + DEL_TAB; + estr << "}" << endl; + if (i != namespaces.size() - 1) estr << endl; + } + + // generate module imports + str << "import * as " << IDL_NAMESPACE_STR << "Stream from \"" << _sStreamPath << "\";" << endl; + str << "import * as base from \"./" + << TC_File::excludeFileExt(TC_File::extractFileName(cPtr->getFileName())) << "\";" << endl; + + for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) + { + if (it->second.sModule.empty()) continue; + + if (estr.str().find(it->second.sModule + ".") == string::npos) continue; + + str << "import * as " << it->second.sModule << " from \"" << TC_File::excludeFileExt(it->second.sFile) << "\";" << endl; + } + + str << endl; + str << estr.str(); + + TC_File::makeDirRecursive(_sToPath); + makeUTF8File(sFileName, str.str()); +} diff --git a/tools/tars2node/gen_ts.cpp b/tools/tars2node/gen_ts.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac54f985895f1a5ba50e25891b48894eee8b805f --- /dev/null +++ b/tools/tars2node/gen_ts.cpp @@ -0,0 +1,446 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT 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 "code_generator.h" + +string CodeGenerator::generateTS(const EnumPtr &pPtr, const string &sNamespace) +{ + ostringstream s; + + INC_TAB; + s << TAB << "export enum " << pPtr->getId() << " {" << endl; + + INC_TAB; + int nenum = -1; + bool bDependent = false; + vector& member = pPtr->getAllMemberPtr(); + for (size_t i = 0; i < member.size(); i++) + { + bDependent |= isDependent(sNamespace, member[i]->getId()); + if (member[i]->hasDefault()) + { + nenum = TC_Common::strto(member[i]->def()); + } + else + { + nenum++; + } + s << TAB << member[i]->getId() << " = " << TC_Common::tostr(nenum) << ((i < member.size() - 1) ? "," : "") << endl; + } + + DEL_TAB; + s << TAB << "}" << endl << endl; + + s << TAB << "export namespace " << pPtr->getId() << " {" << endl; + INC_TAB; + s << TAB << "export const _classname = \"" << sNamespace << "." << pPtr->getId() << "\";" << endl; + s << TAB << "export function _write(os: " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "OutputStream, tag: number, val: number) { return os.writeInt32(tag, val); }" << endl; + s << TAB << "export function _read(is: " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "InputStream, tag: number, def?: number) { return is.readInt32(tag, true, def); }" << endl; + DEL_TAB; + s << TAB << "}" << endl << endl; + + DEL_TAB; + + if (!_bMinimalMembers || _bEntry || bDependent || isDependent(sNamespace, pPtr->getId())) { + return s.str(); + } else { + return ""; + } +} + +string CodeGenerator::generateTS(const ConstPtr &pPtr, const string &sNamespace, bool &bNeedStream) +{ + if (_bMinimalMembers && !_bEntry && !isDependent(sNamespace, pPtr->getTypeIdPtr()->getId())) + { + return ""; + } + + ostringstream s; + if (_bStringBinaryEncoding && GET_CONST_GRAMMAR_PTR(pPtr)->t == CONST_GRAMMAR(STRING)) + { + bNeedStream = true; + } + + INC_TAB; + s << TAB << "export const " << pPtr->getTypeIdPtr()->getId() << ": " + << getTsType(pPtr->getTypeIdPtr()->getTypePtr()) << " = " + << getDefault(pPtr->getTypeIdPtr(), GET_CONST_GRAMMAR_PTR(pPtr)->v, sNamespace, false, true) << ";" + << endl; + DEL_TAB; + return s.str(); +} + +string CodeGenerator::generateTS(const StructPtr &pPtr, const string &sNamespace, bool &bNeedAssert, bool &bQuickFunc) +{ + if (_bMinimalMembers && !_bEntry && !isDependent(sNamespace, pPtr->getId())) + { + return ""; + } + + string sStructName = pPtr->getId() + "$OBJ"; + vector &member = pPtr->getAllMemberPtr(); + INC_TAB; + + // Struct + ostringstream s; + s << TAB << "export class " << pPtr->getId() << " {" << endl; + INC_TAB; + + // class members + for (size_t i = 0; i < member.size(); i++) + { + s << TAB << (member[i]->getId()) << ": " + << getTsType(member[i]->getTypePtr()) << " = " + << getDefault(member[i], member[i]->def(), sNamespace, true, true) << ";" << endl; + } + if (member.size() > 0) + { + s << endl; + } + + // _classname, _proto_struct_name_ + s << TAB << "protected _proto_struct_name_ = \"\";" << endl; + s << TAB << "protected _classname = \"" << sNamespace << "." << pPtr->getId() << "\";" << endl; + s << TAB << "protected static _classname = \"" << sNamespace << "." << pPtr->getId() << "\";" << endl; + + // _write, _read + s << TAB << "protected static _write(os: " << IDL_NAMESPACE_STR << "Stream.TarsOutputStream, tag: number, val: any) { os.writeStruct(tag, val); }" << endl; + s << TAB << "protected static _read(is: " << IDL_NAMESPACE_STR << "Stream.TarsInputStream, tag: number, def?: any) { return is.readStruct(tag, true, def); }" << endl; + + // _readFrom + s << TAB << "protected static _readFrom(is: " << IDL_NAMESPACE_STR << "Stream.TarsInputStream) {" << endl; + INC_TAB; + + s << TAB << "const tmp = new " << pPtr->getId() << ";" << endl; + for (size_t i = 0; i < member.size(); i++) + { + string sFuncName = toFunctionName(member[i], "read"); + s << TAB << "tmp." << member[i]->getId() << " = is." << sFuncName << "(" << member[i]->getTag() + << ", " << (member[i]->isRequire() ? "true" : "false") << ", "; + + if (isSimple(member[i]->getTypePtr())) + { + s << getDefault(member[i], member[i]->def(), sNamespace, true, true) + << representArgument(member[i]->getTypePtr()); + } + else + { + s << getDataType(member[i]->getTypePtr(), true); + } + + s << ");" << endl; + } + s << TAB << "return tmp;" << endl; + DEL_TAB; // end of _readFrom + s << TAB << "}" << endl << endl; + + // _writeTo + s << TAB << "protected _writeTo(os: " << IDL_NAMESPACE_STR << "Stream.TarsOutputStream) {" << endl; + INC_TAB; + for (size_t i = 0; i < member.size(); i++) + { + string sFuncName = toFunctionName(member[i], "write"); + + s << TAB << "os." << sFuncName << "(" << member[i]->getTag() << ", this." << member[i]->getId() + << representArgument(member[i]->getTypePtr()) << ");" << endl; + } + DEL_TAB; // end of _writeTo + s << TAB << "}" << endl; + + /* + * Size Optimize: + * Remove support. + * Remove toBinBuffer, readFromObject, toObject, new, create members. + */ + if (_iOptimizeLevel != Os) + { + s << endl; + + // _equal + vector key = pPtr->getKey(); + + s << TAB << "protected _equal(" << (key.size() > 0 ? "anItem: any" : "") << ")" << (key.size() > 0 ? ": boolean" : "") << " {" << endl; + INC_TAB; + + if (key.size() > 0) + { + s << TAB << "return "; + + for (size_t i = 0; i < key.size(); i++) + { + for (size_t ii = 0; ii < member.size(); ii++) + { + if (key[i] != member[ii]->getId()) + { + continue; + } + + if (isSimple(member[i]->getTypePtr())) + { + s << (i==0?"":TAB + TAB) << "this." << key[i] << " === " << "anItem." << key[i]; + } + else + { + s << (i==0?"":TAB + TAB) << "this._equal(" << "anItem)"; + } + } + + if (i != key.size() - 1) + { + s << " && " << endl; + } + } + + s << ";" << endl; + } + else + { + bNeedAssert = true; + s << TAB << "assert.fail(\"this structure not define key operation\");" << endl; + } + + DEL_TAB; + s << TAB << "}" << endl << endl; + + // _genKey + s << TAB << "protected _genKey() {" << endl; + INC_TAB; + s << TAB << "if (!this._proto_struct_name_) {" << endl; + INC_TAB; + s << TAB << "this._proto_struct_name_ = \"STRUCT\" + Math.random();" << endl; + DEL_TAB; + s << TAB << "}" << endl; + s << TAB << "return this._proto_struct_name_;" << endl; + DEL_TAB; + s << TAB << "}" << endl << endl; + + // toObject + s << TAB << "toObject(): " << pPtr->getId() << ".Object { "<< endl; + INC_TAB; + s << TAB << "return {" << endl; + + for (size_t i = 0; i < member.size(); i++) + { + INC_TAB; + if (i > 0 && i < member.size()) { + s << "," << endl; + } + + if (isSimple(member[i]->getTypePtr())) { + s << TAB << member[i]->getId() << ": this." << member[i]->getId(); + } + else { + s << TAB << member[i]->getId() << ": this." << member[i]->getId() << ".toObject()"; + } + DEL_TAB; + } + + s << endl; + s << TAB << "};" << endl; + DEL_TAB; + s << TAB << "}" << endl << endl; + + // readFromObject + s << TAB << "readFromObject(json: " << pPtr->getId() << ".Object) { "<< endl; + INC_TAB; + + for (size_t i = 0; i < member.size(); i++) + { + if (isSimple(member[i]->getTypePtr())) { + s << TAB << "_hasOwnProperty.call(json, \"" << member[i]->getId() << "\") && (this." << member[i]->getId() << " = json." << member[i]->getId() << (member[i]->isRequire() ? "" : "!") << ");" << endl; + } else { + s << TAB << "_hasOwnProperty.call(json, \"" << member[i]->getId() << "\") && (this." << member[i]->getId() << ".readFromObject(json." << member[i]->getId() << (member[i]->isRequire() ? "" : "!") << "));" << endl; + } + bQuickFunc = true; + } + + s << TAB << "return this;" << endl; + + DEL_TAB; + s << TAB << "}" << endl << endl; + + // toBinBuffer + s << TAB << "toBinBuffer() {" << endl; + INC_TAB; + s << TAB << "const os = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "OutputStream();" << endl; + s << TAB << "this._writeTo(os);" << endl; + s << TAB << "return os.getBinBuffer();" << endl; + DEL_TAB; + s << TAB << "}" << endl << endl; + + // new + s << TAB << "static new() {" << endl; + INC_TAB; + s << TAB << "return new " << pPtr->getId() << "();" << endl; + DEL_TAB; + s << TAB << "}" << endl << endl; + + // create + s << TAB << "static create(is: " << IDL_NAMESPACE_STR << "Stream.TarsInputStream) {" << endl; + INC_TAB; + s << TAB << "return " << sNamespace << "." << pPtr->getId() << "._readFrom(is);" << endl; + DEL_TAB; + s << TAB << "}" << endl; + } + + DEL_TAB; // end of Struct + s << TAB << "}" << endl << endl; + + // Additional namespace + s << TAB << "export namespace " << pPtr->getId() << " {" << endl; + INC_TAB; + s << TAB << "export interface Object {" << endl; + INC_TAB; + for (size_t i = 0; i < member.size(); i++) + { + const string &sType = getTsType(member[i]->getTypePtr(), false); + s << TAB << (member[i]->getId()) << (member[i]->isRequire() ? ": " : "?: ") << (!sType.empty() ? sType : "never") << ";" << endl; + } + DEL_TAB; + s << TAB << "}" << endl; + DEL_TAB; + s << TAB << "}" << endl; + + DEL_TAB; + return s.str(); +} + +string CodeGenerator::generateTS(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedAssert, bool &bQuickFunc) +{ + // struct + ostringstream sstr; + vector ss(pPtr->getAllStructPtr()); + for (size_t last = 0; last != ss.size() && ss.size() != 0;) + { + last = ss.size(); + for (vector::iterator iter=ss.begin(); iter!=ss.end();) + { + string str = generateTS(*iter, pPtr->getId(), bNeedAssert, bQuickFunc); + if (!str.empty()) + { + sstr << str << endl; + iter = ss.erase(iter); + } + else + { + iter++; + } + } + } + + // const + ostringstream cstr; + vector &cs = pPtr->getAllConstPtr(); + for (size_t i = 0; i < cs.size(); i++) + { + cstr << generateTS(cs[i], pPtr->getId(), bNeedStream); + } + + // enum + ostringstream estr; + vector &es = pPtr->getAllEnumPtr(); + for (size_t i = 0; i < es.size(); i++) + { + estr << generateTS(es[i], pPtr->getId()); + } + + ostringstream kstr; + if (!estr.str().empty()) + { + bNeedStream = true; + kstr << estr.str() << endl; + } + if (!cstr.str().empty()) kstr << cstr.str() << endl; + if (!sstr.str().empty()) + { + bNeedStream = true; + kstr << sstr.str(); + } + + return kstr.str(); +} + +string CodeGenerator::generateTS(const NamespacePtr &pPtr, const string &sContent) +{ + ostringstream str; + if (!sContent.empty()) + { + str << "export namespace " << pPtr->getId() << " {" << endl; + str << sContent; + str << "}" << endl << endl; + } + return str.str(); +} + +void CodeGenerator::generateTS(const ContextPtr &pPtr) +{ + vector namespaces = pPtr->getNamespaces(); + + // generate encoders and decoders + ostringstream estr; + bool bNeedAssert = false; + bool bNeedStream = false; + bool bQuickFunc = false; + for (size_t i = 0; i < namespaces.size(); i++) + { + estr << generateTS(namespaces[i], generateTS(namespaces[i], bNeedStream, bNeedAssert, bQuickFunc)); + } + if (estr.str().empty()) + { + return; + } + + // generate module imports + ostringstream ostr; + if (bNeedAssert) + { + ostr << "import assert = require(\"assert\");" << endl; + } + if (bNeedStream) + { + ostr << "import * as " << IDL_NAMESPACE_STR << "Stream from \"" << _sStreamPath << "\";" << endl; + } + + for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) + { + if (it->second.sModule.empty()) continue; + + if (estr.str().find(it->second.sModule + ".") == string::npos) continue; + + ostr << "import * as " << it->second.sModule << " from \"" << TC_File::excludeFileExt(it->second.sFile) << "\";" << endl; + } + + if (bQuickFunc) + { + ostr << endl; + ostr << "const _hasOwnProperty = Object.prototype.hasOwnProperty;" << endl; + } + + // concat generated code + ostringstream sstr; + sstr << printHeaderRemark("Structure"); + sstr << DISABLE_TSLINT << endl; + sstr << DISABLE_ESLINT << endl; + sstr << endl; + sstr << "/// " << endl; + sstr << ostr.str() << endl; + sstr << estr.str() << endl; + + string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(pPtr->getFileName())) + IDL_TYPE + ".ts"; + + TC_File::makeDirRecursive(_sToPath); + makeUTF8File(sFileName, sstr.str()); +} diff --git a/tools/tars2node/idl_scan.cpp b/tools/tars2node/idl_scan.cpp index 06984f2364222a357b5c4f6357de5b9d06b1d79f..e2d59bb89dc888e154aadc97761adb3670ce0d6c 100644 --- a/tools/tars2node/idl_scan.cpp +++ b/tools/tars2node/idl_scan.cpp @@ -29,7 +29,7 @@ string CodeGenerator::makeName() if (iHigh != 0) { - s << string(1, (char)(iHigh + 65)) << string(1, (char)(iLow + 65)); + s << string(1, (char)(iHigh + 65)) << string(1, (char)(iLow + 65)); } else { @@ -46,7 +46,7 @@ bool CodeGenerator::isDependent(const string& sNamespace, const string& sName) c return _depMembers.find(sNamespace + "::" + sName) != _depMembers.end(); } -string CodeGenerator::findName(const string& sNamespace, const string& sName) +string CodeGenerator::findName(const string& sNamespace, const string& sName, const bool &bBase) { #ifdef DUMP_FIND_NAME cout << "FINDNAME BEGIN:" << sNamespace << "|" << sName << endl; @@ -71,17 +71,24 @@ string CodeGenerator::findName(const string& sNamespace, const string& sName) cout << "DEPMEMBER:" << it->first << "|" << inIter->second.sNamespace << "::" << inIter->second.sName << endl; #endif _depMembers.insert(inIter->second.sNamespace + "::" + inIter->second.sName); + string prefix; + + if (bBase && it->second.sModule.empty()) { + prefix = "base."; + } else if (!it->second.sModule.empty()) { + prefix = it->second.sModule + "."; + } switch (inIter->second.iType) { case ImportFileType::EN_ENUM : // [[fallthrough]] case ImportFileType::EN_STRUCT : { - return it->second.sModule + (it->second.sModule.empty()?"":".") + inIter->second.sNamespace + "." + inIter->second.sName; + return prefix + inIter->second.sNamespace + "." + inIter->second.sName; } case ImportFileType::EN_ENUM_VALUE : { - return it->second.sModule + (it->second.sModule.empty()?"":".") + inIter->second.sNamespace + "." + inIter->second.sTypeName + "." + inIter->second.sName; + return prefix + inIter->second.sNamespace + "." + inIter->second.sTypeName + "." + inIter->second.sName; } default : { diff --git a/tools/tars2node/idl_util.cpp b/tools/tars2node/idl_util.cpp index c7b4d3c88b80ea747bb427ead938cac4ef343c95..28c9ec9404e3ed00a7c89cfc831b7a6953f12f78 100644 --- a/tools/tars2node/idl_util.cpp +++ b/tools/tars2node/idl_util.cpp @@ -68,26 +68,77 @@ string CodeGenerator::toFunctionName(const TypeIdPtr& pPtr, const string& sActio return ""; } -bool CodeGenerator::isRawOrString(const TypePtr& pPtr) const +string CodeGenerator::representArgument(const TypePtr& pPtr) const { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); if (bPtr) { - if (_bUseStringRepresent && bPtr->kind() == Builtin::KindLong) + if (bPtr->kind() == Builtin::KindLong && _iLongType != CodeGenerator::Number) { - return true; + stringstream str; + str << ", " << _iLongType; + return str.str(); } if (_bStringBinaryEncoding && bPtr->kind() == Builtin::KindString) { - return true; + return ", 1"; } } - return false; + return ""; } -string CodeGenerator::getDataType(const TypePtr & pPtr) +string CodeGenerator::getClassName(const TypePtr& pPtr) +{ + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); + if (bPtr) + { + switch (bPtr->kind()) + { + case Builtin::KindBool : return "bool"; + case Builtin::KindString : return "string"; + case Builtin::KindByte : return "char"; + case Builtin::KindShort : return "short"; + case Builtin::KindInt : return "int32"; + case Builtin::KindLong : return "int64"; + case Builtin::KindFloat : return "float"; + case Builtin::KindDouble : return "double"; + default : assert(false); + } + } + + VectorPtr vPtr = VectorPtr::dynamicCast(pPtr); + if (vPtr) + { + return "list(" + getClassName(vPtr->getTypePtr()) + ")"; + } + + StructPtr sPtr = StructPtr::dynamicCast(pPtr); + if (sPtr) + { + vector vecNames = TC_Common::sepstr(sPtr->getSid(), "::"); + assert(vecNames.size() == 2); + + return vecNames[0] + "." + vecNames[1]; + } + + MapPtr mPtr = MapPtr::dynamicCast(pPtr); + if (mPtr) + { + return "map(" + getClassName(mPtr->getLeftTypePtr()) + ", " + getClassName(mPtr->getRightTypePtr()) + ")"; + } + + EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); + if (ePtr) + { + return "int32"; + } + + return "void"; +} + +string CodeGenerator::getDataType(const TypePtr& pPtr, const bool &bCastEnumAsAny) { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); if (bPtr) @@ -114,8 +165,7 @@ string CodeGenerator::getDataType(const TypePtr & pPtr) { return IDL_NAMESPACE_STR + "Stream.BinBuffer"; } - - return IDL_NAMESPACE_STR + "Stream.List(" + getDataType(vPtr->getTypePtr()) + (isRawOrString(vPtr->getTypePtr()) ? ", 1" : "") + ")"; + return IDL_NAMESPACE_STR + "Stream.List(" + getDataType(vPtr->getTypePtr(), bCastEnumAsAny) + representArgument(vPtr->getTypePtr()) + ")"; } StructPtr sPtr = StructPtr::dynamicCast(pPtr); @@ -130,20 +180,16 @@ string CodeGenerator::getDataType(const TypePtr & pPtr) MapPtr mPtr = MapPtr::dynamicCast(pPtr); if (mPtr) { - bool bLeft = isRawOrString(mPtr->getLeftTypePtr()); - bool bRight = isRawOrString(mPtr->getRightTypePtr()); - - if (!bRight && !bLeft) { - return IDL_NAMESPACE_STR + "Stream.Map(" + getDataType(mPtr->getLeftTypePtr()) + ", " + getDataType(mPtr->getRightTypePtr()) + ")"; - } else if (bRight && bLeft) { - return IDL_NAMESPACE_STR + "Stream.Map(" + getDataType(mPtr->getLeftTypePtr()) + ", " + getDataType(mPtr->getRightTypePtr()) + ", 1, 1)"; - } else if (bRight) { - return IDL_NAMESPACE_STR + "Stream.Map(" + getDataType(mPtr->getLeftTypePtr()) + ", " + getDataType(mPtr->getRightTypePtr()) + ", 0, 1)"; - } else if (bLeft) { - return IDL_NAMESPACE_STR + "Stream.Map(" + getDataType(mPtr->getLeftTypePtr()) + ", " + getDataType(mPtr->getRightTypePtr()) + ", 1)"; - } else { - assert(false); + string sLeft = representArgument(mPtr->getLeftTypePtr()); + string sRight = representArgument(mPtr->getRightTypePtr()); + + if (sLeft.empty() && !sRight.empty()) + { + sLeft = ", 0"; } + + return IDL_NAMESPACE_STR + "Stream.Map(" + getDataType(mPtr->getLeftTypePtr(), bCastEnumAsAny) + ", " + + getDataType(mPtr->getRightTypePtr(), bCastEnumAsAny) + sLeft + sRight + ")"; } EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); @@ -151,15 +197,16 @@ string CodeGenerator::getDataType(const TypePtr & pPtr) { vector vecNames = TC_Common::sepstr(ePtr->getSid(), "::"); assert(vecNames.size() == 2); + string suffix = bCastEnumAsAny ? " as any" : ""; - return findName(vecNames[0], vecNames[1]); + return findName(vecNames[0], vecNames[1]) + suffix; } assert(false); return ""; } -string CodeGenerator::getDtsType(const TypePtr &pPtr, const bool bStream) +string CodeGenerator::getTsType(const TypePtr &pPtr, const bool bStream, const bool bBase) { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); if (bPtr) @@ -167,13 +214,22 @@ string CodeGenerator::getDtsType(const TypePtr &pPtr, const bool bStream) switch (bPtr->kind()) { case Builtin::KindBool : return "boolean"; - case Builtin::KindString : return _bStringBinaryEncoding ? (bStream ? (IDL_NAMESPACE_STR + "Stream.BinBuffer") : "Buffer") : "string"; + case Builtin::KindString : return _bStringBinaryEncoding ? "Buffer" : "string"; case Builtin::KindByte : return "number"; case Builtin::KindShort : return "number"; case Builtin::KindInt : return "number"; - case Builtin::KindLong : return _bUseStringRepresent ? "string" : "number"; case Builtin::KindFloat : return "number"; case Builtin::KindDouble : return "number"; + case Builtin::KindLong : + { + switch (_iLongType) + { + case CodeGenerator::Number : return "number"; + case CodeGenerator::String : return "string"; + case CodeGenerator::BigInt : return "bigint"; + default : assert(false); + } + } default : assert(false); } } @@ -186,7 +242,7 @@ string CodeGenerator::getDtsType(const TypePtr &pPtr, const bool bStream) { return bStream ? (IDL_NAMESPACE_STR + "Stream.BinBuffer") : "Buffer"; } - return (bStream ? (IDL_NAMESPACE_STR + "Stream.List") : "Array") + string("<") + getDtsType(vPtr->getTypePtr(), bStream) + string(">"); + return (bStream ? (IDL_NAMESPACE_STR + "Stream.List") : "Array") + string("<") + getTsType(vPtr->getTypePtr(), bStream, bBase) + string(">"); } StructPtr sPtr = StructPtr::dynamicCast(pPtr); @@ -195,7 +251,7 @@ string CodeGenerator::getDtsType(const TypePtr &pPtr, const bool bStream) vector vecNames = TC_Common::sepstr(sPtr->getSid(), "::"); assert(vecNames.size() == 2); - return findName(vecNames[0], vecNames[1]) + (bStream ? "" : "$OBJ"); + return findName(vecNames[0], vecNames[1], bBase) + (bStream ? "" : ".Object"); } MapPtr mPtr = MapPtr::dynamicCast(pPtr); @@ -203,20 +259,24 @@ string CodeGenerator::getDtsType(const TypePtr &pPtr, const bool bStream) { if (bStream) { - return IDL_NAMESPACE_STR + "Stream.Map<" + getDtsType(mPtr->getLeftTypePtr(), bStream) + ", " + getDtsType(mPtr->getRightTypePtr(), bStream) + ">"; + // In current version (20190311) of the streaming library, + // TypeScript cannot infer enum type over conditional type correctly. + // So use `HeroMap` instead of `Map` to solve this problem. + EnumPtr keyTypePtr = EnumPtr::dynamicCast(mPtr->getLeftTypePtr()); + string mapName = keyTypePtr ? "HeroMap" : "Map"; + + return IDL_NAMESPACE_STR + "Stream." + mapName + "<" + getTsType(mPtr->getLeftTypePtr(), bStream) + ", " + getTsType(mPtr->getRightTypePtr(), bStream, bBase) + ">"; } else { - const string& sLeftType = getDtsType(mPtr->getLeftTypePtr(), bStream); - if (sLeftType == "number" || sLeftType == "string") + const string& sLeftType = getTsType(mPtr->getLeftTypePtr(), bStream, bBase); + const string& sRightType = getTsType(mPtr->getRightTypePtr(), bStream, bBase); + if (isSimple(mPtr->getLeftTypePtr())) { - return "{[key: " + getDtsType(mPtr->getLeftTypePtr(), bStream) + "]: " + getDtsType(mPtr->getRightTypePtr(), bStream) + "}"; + const string& recordKeyType = sLeftType == "number" ? "number" : "string"; + return "Record<" + recordKeyType + ", " + sRightType + ">"; } - else if (isSimple(mPtr->getLeftTypePtr()) && sLeftType != "Buffer") - { - return "object"; - } - else + else { return ""; } @@ -229,7 +289,7 @@ string CodeGenerator::getDtsType(const TypePtr &pPtr, const bool bStream) vector vecNames = TC_Common::sepstr(ePtr->getSid(), "::"); assert(vecNames.size() == 2); - return findName(vecNames[0], vecNames[1]); + return findName(vecNames[0], vecNames[1], bBase); } assert(false); @@ -269,21 +329,16 @@ bool CodeGenerator::isBinBuffer(const TypePtr & pPtr) const return false; } -string CodeGenerator::getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string& sNamespace) -{ - return getDefault(pPtr, sDefault, sNamespace, true); -} - -string CodeGenerator::getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string& sNamespace, const bool bGlobal) +string CodeGenerator::getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string& sNamespace, const bool &bGlobal, const bool &bCastEnumAsAny) { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr()); if (bPtr) { switch (bPtr->kind()) { - case Builtin::KindBool : + case Builtin::KindBool : return sDefault.empty() ? "false" : sDefault; - case Builtin::KindString : + case Builtin::KindString : { if (_bStringBinaryEncoding) { @@ -308,13 +363,13 @@ string CodeGenerator::getDefault(const TypeIdPtr & pPtr, const string &sDefault, { if (TC_Common::tostr(TC_Common::strto(sTemp)) != sTemp) { - //有可能是枚举值,在枚举值中查找 + // lookup in the enum when it is a enum vector vecNames = TC_Common::sepstr(sDefault, "::"); if (vecNames.size() == 2) { sTemp = findName(vecNames[0], vecNames[1]); } - else + else { sTemp = findName(sNamespace, sDefault); } @@ -326,18 +381,27 @@ string CodeGenerator::getDefault(const TypeIdPtr & pPtr, const string &sDefault, sTemp = "0"; } - if (_bUseStringRepresent) + if (bPtr->kind() == Builtin::KindLong) { - if (bPtr->kind() == Builtin::KindLong) + switch (_iLongType) { - sTemp = "\"" + sTemp + "\""; + case CodeGenerator::String: + { + sTemp = "\"" + sTemp + "\""; + break; + } + case CodeGenerator::BigInt: + { + sTemp = sTemp + "n"; + break; + } } } return sTemp; } case Builtin::KindFloat : // [[fallthrough]] - case Builtin::KindDouble : + case Builtin::KindDouble : return sDefault.empty()?"0.0":sDefault; default : assert(false); @@ -384,7 +448,7 @@ string CodeGenerator::getDefault(const TypeIdPtr & pPtr, const string &sDefault, if (bGlobal) { - return "new " + getDataType(pPtr->getTypePtr()); + return "new " + getDataType(pPtr->getTypePtr(), bCastEnumAsAny); } return sDefault; diff --git a/tools/tars2node/main.cpp b/tools/tars2node/main.cpp index e5cd317ca72ad8e06f3d22bf6f23629b55d5bed4..55f4f00de8a09613be574418e8f5ac4c829362f6 100644 --- a/tools/tars2node/main.cpp +++ b/tools/tars2node/main.cpp @@ -26,21 +26,24 @@ void usage() { cout << "Version : " << GENERATOR_VERSION << endl; cout << "Usage : " << EXECUTE_FILENAME << " [OPTION] " << "*." << TC_Common::lower(IDL_TYPE) << " file" << endl; - cout << " --version print " << EXECUTE_FILENAME << " version" << endl; - cout << " --rpc-path=DIRECTORY specify the path of rpc module." << endl; - cout << " --stream-path=DIRECTORY specify the path of stream module." << endl; - cout << " --allow-reserved-namespace allow you to use reserved word as a namespace." << endl; - cout << " --dir=DIRECTORY generate source file to DIRECTORY." << endl; - cout << " --relative use current path." << endl; - cout << " --base=DIRECTORY where to search " << IDL_TYPE << " files." << endl; - cout << " --r generate source all " << IDL_TYPE << " files." << endl; - cout << " --r-minimal minimize the dependent members." << endl; - cout << " --r-reserved list of names(split by \",\") that should be keeped." << endl; - cout << " --client just for client side source file." << endl; - cout << " --server just for server side source file." << endl; - cout << " --dts generate d.ts file." << endl; - cout << " --use-string-represent use string represent long type." << endl; - cout << " --string-binary-encoding get string raw bytes ." << endl; + cout << " --version print " << EXECUTE_FILENAME << " version" << endl; + cout << " --rpc-path=[DIRECTORY] specify the path of rpc module." << endl; + cout << " --stream-path=[DIRECTORY] specify the path of stream module." << endl; + cout << " --allow-reserved-namespace allow you to use reserved word as a namespace." << endl; + cout << " --dir=DIRECTORY generate source file to DIRECTORY." << endl; + cout << " --relative use current path." << endl; + cout << " --base=DIRECTORY where to search " << IDL_TYPE << " files." << endl; + cout << " --r generate source all " << IDL_TYPE << " files." << endl; + cout << " --r-minimal minimize the dependent members." << endl; + cout << " --r-reserved list of names(split by \",\") that should be keeped." << endl; + cout << " --client just for client side source file." << endl; + cout << " --server just for server side source file." << endl; + cout << " --ts generate typescript file." << endl; + cout << " --dts generate d.ts file." << endl; + cout << " --long-type=[number|string|bigint] use represent type, default is ." << endl; + cout << " --string-binary-encoding get string raw bytes ." << endl; + cout << " --enum-reverse-mappings reverse mapping from enum values to enum names." << endl; + cout << " --optimize=[0|s] support \"s\" to reduce code size, default is 0." << endl; cout << endl; cout << EXECUTE_FILENAME << " support type: boolean char short int long float double list map" << endl; @@ -117,7 +120,8 @@ int main(int argc, char* argv[]) #undef ALLOW_USE_RESERVED_NAMESPACE #undef ALLOW_USE_RESERVED_NAMESPACE_BASE #undef ALLOW_USE_RESERVED_NAMESPACE_V - + + g_parse->setTars(option.hasParam("with-tars")); g_parse->setUseCurrentPath(option.hasParam("relative")); CodeGenerator generator; @@ -127,10 +131,38 @@ int main(int argc, char* argv[]) generator.setEnableServer(option.hasParam("server")); generator.setTargetPath(option.hasParam("dir")?option.getValue("dir"):"./"); generator.setUseSpecialPath(option.hasParam("relative")); - generator.setUseStringRepresent(option.hasParam("use-string-represent")); generator.setStringBinaryEncoding(option.hasParam("string-binary-encoding")); + generator.setEnumReverseMappings(option.hasParam("enum-reverse-mappings")); + generator.setEnableTS(option.hasParam("ts")); generator.setEnableDTS(option.hasParam("dts")); + if (option.hasParam("long-type")) + { + string longType = TC_Common::lower(option.getValue("long-type")); + if (longType == "string") + { + generator.setLongType(CodeGenerator::String); + } + else if (longType == "bigint") + { + generator.setLongType(CodeGenerator::BigInt); + } + + } + + if (option.hasParam("optimize")) + { + string level = TC_Common::lower(option.getValue("optimize")); + if (level == "s") + { + generator.setOptimize(CodeGenerator::Os); + } + else + { + generator.setOptimize(CodeGenerator::O0); + } + } + bool _bRecursive = option.hasParam("r"); bool _bMinimalMembers = option.hasParam("r-minimal"); diff --git a/tools/tarsgrammar/CMakeLists.txt b/tools/tarsgrammar/CMakeLists.txt index 7b1cf3f61d2cefc6926c0003892e73ddf0671245..11d80fcb585c8290f6cb9e551d288644191a57de 100644 --- a/tools/tarsgrammar/CMakeLists.txt +++ b/tools/tarsgrammar/CMakeLists.txt @@ -1,4 +1,61 @@ +macro(complice_lex OUT_DEPENDS_LEX_LIST) + set(DEPENDS_LIST) + + FILE(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/*.l") + + foreach (FILE ${SRC_LIST}) + + get_filename_component(NAME_WE ${FILE} NAME_WE) + + set(LEX_IN ${FILE}) + set(LEX_CPP ${NAME_WE}.lex.cpp) + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${LEX_CPP} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${LEX_IN} + COMMAND flex --nounist ${LEX_IN} + COMMENT "flex --nounist ${LEX_IN}") + + list(APPEND DEPENDS_LIST ${CMAKE_CURRENT_SOURCE_DIR}/${LEX_CPP}) + + get_filename_component(PATH ${FILE} PATH) + + endforeach (FILE) + + set(OUT_DEPENDS_LEX_LIST ${DEPENDS_LIST}) + +endmacro() + +macro(complice_yacc OUT_DEPENDS_YACC_LIST) + set(DEPENDS_LIST) + + FILE(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/*.y") + + foreach (FILE ${SRC_LIST}) + + get_filename_component(NAME_WE ${FILE} NAME_WE) + + set(YACC_IN ${FILE}) + set(YACC_H ${NAME_WE}.tab.hpp) + set(YACC_CPP ${NAME_WE}.tab.cpp) + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${YACC_H} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${YACC_IN} + COMMAND bison ${YACC_IN} -o ${YACC_CPP} + COMMENT "bison ${YACC_IN} -o ${YACC_CPP}") + + list(APPEND DEPENDS_LIST ${CMAKE_CURRENT_SOURCE_DIR}/${YACC_H}) + + get_filename_component(PATH ${FILE} PATH) + + endforeach (FILE) + +endmacro() + ########################################################################################## #生成.l和.y文件生成的代码文件copy到tarsparse目录下 @@ -27,9 +84,6 @@ foreach (FILE ${SRC_LEX_LIST}) #设置依赖 list(APPEND OUT_DEPENDS_LEX_LIST ${CP_SOURCE_CPP_DIR}/${LEX_CPP}) - #设置需要清除的.h文件 -# list(APPEND CLEAN_LIST ${CP_SOURCE_CPP_DIR}/${LEX_CPP}) - endforeach () set(OUT_DEPENDS_YACC_LIST) @@ -56,15 +110,7 @@ foreach (FILE ${SRC_YACC_LIST}) #设置依赖 list(APPEND OUT_DEPENDS_YACC_LIST ${CP_SOURCE_H_DIR}/${YACC_H}) - #设置需要清除的.h文件 -# list(APPEND CLEAN_LIST ${CP_SOURCE_H_DIR}/${YACC_H}) -# list(APPEND CLEAN_LIST ${CP_SOURCE_H_DIR}/${YACC_CPP}) - endforeach () -#设置需要清除的文件 -#set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CLEAN_LIST}") - add_custom_target(COPY-LEX-YACC ALL DEPENDS ${OUT_DEPENDS_LEX_LIST} ${OUT_DEPENDS_YACC_LIST}) -#add_custom_target(COPY-LEX-YACC ALL DEPENDS ${OUT_DEPENDS_LEX_LIST} ${CP_SOURCE_CPP_DIR}/${LEX_CPP} ${OUT_DEPENDS_YACC_LIST} ${CP_SOURCE_H_DIR}/${YACC_H}) diff --git a/tools/tarsgrammar/tars.tab.cpp b/tools/tarsgrammar/tars.tab.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d5e1136b10f2290410445f21591fb762cf7f27e --- /dev/null +++ b/tools/tarsgrammar/tars.tab.cpp @@ -0,0 +1,3124 @@ +/* A Bison parser, made by GNU Bison 2.3. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.3" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + TARS_VOID = 258, + TARS_STRUCT = 259, + TARS_BOOL = 260, + TARS_BYTE = 261, + TARS_SHORT = 262, + TARS_INT = 263, + TARS_DOUBLE = 264, + TARS_FLOAT = 265, + TARS_LONG = 266, + TARS_STRING = 267, + TARS_VECTOR = 268, + TARS_MAP = 269, + TARS_NAMESPACE = 270, + TARS_INTERFACE = 271, + TARS_IDENTIFIER = 272, + TARS_OUT = 273, + TARS_OP = 274, + TARS_KEY = 275, + TARS_ROUTE_KEY = 276, + TARS_REQUIRE = 277, + TARS_OPTIONAL = 278, + TARS_CONST_INTEGER = 279, + TARS_CONST_FLOAT = 280, + TARS_FALSE = 281, + TARS_TRUE = 282, + TARS_STRING_LITERAL = 283, + TARS_SCOPE_DELIMITER = 284, + TARS_CONST = 285, + TARS_ENUM = 286, + TARS_UNSIGNED = 287, + BAD_CHAR = 288 + }; +#endif +/* Tokens. */ +#define TARS_VOID 258 +#define TARS_STRUCT 259 +#define TARS_BOOL 260 +#define TARS_BYTE 261 +#define TARS_SHORT 262 +#define TARS_INT 263 +#define TARS_DOUBLE 264 +#define TARS_FLOAT 265 +#define TARS_LONG 266 +#define TARS_STRING 267 +#define TARS_VECTOR 268 +#define TARS_MAP 269 +#define TARS_NAMESPACE 270 +#define TARS_INTERFACE 271 +#define TARS_IDENTIFIER 272 +#define TARS_OUT 273 +#define TARS_OP 274 +#define TARS_KEY 275 +#define TARS_ROUTE_KEY 276 +#define TARS_REQUIRE 277 +#define TARS_OPTIONAL 278 +#define TARS_CONST_INTEGER 279 +#define TARS_CONST_FLOAT 280 +#define TARS_FALSE 281 +#define TARS_TRUE 282 +#define TARS_STRING_LITERAL 283 +#define TARS_SCOPE_DELIMITER 284 +#define TARS_CONST 285 +#define TARS_ENUM 286 +#define TARS_UNSIGNED 287 +#define BAD_CHAR 288 + + + + +/* Copy the first part of user declarations. */ +#line 17 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + +#include +#include +#include + +using namespace std; + +#define YYSTYPE GrammarBasePtr + +#include "parse.h" +#define YYDEBUG 1 +#define YYINITDEPTH 10000 + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef int YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ + + +/* Line 216 of yacc.c. */ +#line 186 "tars.tab.cpp" + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int i) +#else +static int +YYID (i) + int i; +#endif +{ + return i; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 75 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 565 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 46 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 42 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 137 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 199 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 288 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 41, 42, 2, 37, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 43, 34, + 44, 38, 45, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 39, 2, 40, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 35, 2, 36, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint16 yyprhs[] = +{ + 0, 0, 3, 5, 6, 11, 12, 17, 19, 20, + 22, 24, 26, 28, 30, 32, 33, 39, 42, 45, + 49, 51, 53, 55, 59, 60, 61, 68, 69, 77, + 79, 83, 84, 90, 93, 96, 100, 104, 106, 107, + 109, 113, 116, 118, 120, 121, 123, 127, 130, 135, + 138, 143, 145, 147, 149, 151, 152, 158, 161, 164, + 167, 171, 173, 174, 176, 180, 186, 192, 196, 199, + 202, 205, 207, 209, 211, 213, 215, 217, 219, 223, + 228, 231, 237, 241, 246, 249, 251, 253, 257, 259, + 263, 265, 267, 270, 272, 275, 277, 280, 282, 284, + 286, 288, 290, 292, 294, 299, 303, 308, 311, 318, + 322, 324, 327, 331, 333, 335, 337, 339, 341, 343, + 345, 347, 349, 351, 353, 355, 357, 359, 361, 363, + 365, 367, 369, 371, 373, 375, 377, 379 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 47, 0, -1, 48, -1, -1, 51, 49, 34, 48, + -1, -1, 1, 34, 50, 48, -1, 51, -1, -1, + 57, -1, 62, -1, 73, -1, 59, -1, 52, -1, + 80, -1, -1, 54, 53, 35, 55, 36, -1, 31, + 17, -1, 31, 87, -1, 56, 37, 55, -1, 56, + -1, 17, -1, 87, -1, 17, 38, 79, -1, -1, + -1, 15, 17, 58, 35, 48, 36, -1, -1, 20, + 39, 86, 37, 60, 61, 40, -1, 17, -1, 61, + 37, 17, -1, -1, 64, 63, 35, 65, 36, -1, + 16, 17, -1, 16, 87, -1, 66, 34, 65, -1, + 1, 34, 65, -1, 66, -1, -1, 67, -1, 68, + 70, 41, -1, 69, 19, -1, 82, -1, 3, -1, + -1, 81, -1, 70, 37, 81, -1, 72, 81, -1, + 70, 37, 72, 81, -1, 71, 81, -1, 70, 37, + 71, 81, -1, 72, -1, 71, -1, 21, -1, 18, + -1, -1, 75, 74, 35, 76, 36, -1, 4, 17, + -1, 4, 87, -1, 4, 1, -1, 77, 34, 76, + -1, 77, -1, -1, 78, -1, 24, 22, 81, -1, + 24, 22, 81, 38, 79, -1, 24, 23, 81, 38, + 79, -1, 24, 23, 81, -1, 22, 81, -1, 23, + 81, -1, 24, 81, -1, 81, -1, 24, -1, 25, + -1, 28, -1, 26, -1, 27, -1, 17, -1, 86, + 29, 17, -1, 30, 81, 38, 79, -1, 82, 17, + -1, 82, 17, 39, 24, 40, -1, 82, 42, 17, + -1, 82, 17, 43, 24, -1, 82, 87, -1, 82, + -1, 1, -1, 83, 43, 24, -1, 83, -1, 83, + 43, 1, -1, 5, -1, 6, -1, 32, 6, -1, + 7, -1, 32, 7, -1, 8, -1, 32, 8, -1, + 11, -1, 10, -1, 9, -1, 12, -1, 84, -1, + 85, -1, 86, -1, 13, 44, 82, 45, -1, 13, + 44, 1, -1, 13, 44, 82, 1, -1, 13, 1, + -1, 14, 44, 82, 37, 82, 45, -1, 14, 44, + 1, -1, 17, -1, 29, 17, -1, 86, 29, 17, + -1, 4, -1, 3, -1, 5, -1, 6, -1, 7, + -1, 8, -1, 10, -1, 9, -1, 12, -1, 13, + -1, 20, -1, 14, -1, 15, -1, 16, -1, 18, + -1, 22, -1, 23, -1, 24, -1, 25, -1, 26, + -1, 27, -1, 28, -1, 30, -1, 31, -1, 32, + -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 68, 68, 75, 74, 79, 78, 83, 88, 95, + 99, 103, 107, 110, 114, 124, 123, 146, 159, 170, + 174, 182, 193, 198, 212, 220, 219, 253, 252, 271, + 284, 304, 303, 337, 341, 352, 355, 358, 363, 370, + 376, 393, 422, 423, 434, 436, 447, 458, 470, 482, + 494, 506, 510, 519, 530, 542, 541, 583, 587, 593, + 602, 606, 611, 620, 629, 647, 669, 691, 708, 712, + 716, 720, 729, 739, 749, 757, 765, 773, 786, 806, + 824, 833, 843, 853, 862, 867, 871, 880, 889, 893, + 902, 906, 910, 914, 918, 922, 926, 930, 934, 938, + 942, 946, 950, 954, 972, 976, 980, 984, 993, 997, + 1006, 1009, 1015, 1028, 1031, 1034, 1037, 1040, 1043, 1046, + 1049, 1052, 1055, 1058, 1061, 1064, 1067, 1070, 1073, 1076, + 1079, 1082, 1085, 1088, 1091, 1094, 1097, 1100 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "TARS_VOID", "TARS_STRUCT", "TARS_BOOL", + "TARS_BYTE", "TARS_SHORT", "TARS_INT", "TARS_DOUBLE", "TARS_FLOAT", + "TARS_LONG", "TARS_STRING", "TARS_VECTOR", "TARS_MAP", "TARS_NAMESPACE", + "TARS_INTERFACE", "TARS_IDENTIFIER", "TARS_OUT", "TARS_OP", "TARS_KEY", + "TARS_ROUTE_KEY", "TARS_REQUIRE", "TARS_OPTIONAL", "TARS_CONST_INTEGER", + "TARS_CONST_FLOAT", "TARS_FALSE", "TARS_TRUE", "TARS_STRING_LITERAL", + "TARS_SCOPE_DELIMITER", "TARS_CONST", "TARS_ENUM", "TARS_UNSIGNED", + "BAD_CHAR", "';'", "'{'", "'}'", "','", "'='", "'['", "']'", "')'", + "'*'", "':'", "'<'", "'>'", "$accept", "start", "definitions", "@1", + "@2", "definition", "enum_def", "@3", "enum_id", "enumerator_list", + "enumerator", "namespace_def", "@4", "key_def", "@5", "key_members", + "interface_def", "@6", "interface_id", "interface_exports", + "interface_export", "operation", "operation_preamble", "return_type", + "parameters", "routekey_qualifier", "out_qualifier", "struct_def", "@7", + "struct_id", "struct_exports", "data_member", "struct_type_id", + "const_initializer", "const_def", "type_id", "type", "type_no", "vector", + "map", "scoped_name", "keyword", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 59, 123, 125, 44, 61, 91, + 93, 41, 42, 58, 60, 62 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 46, 47, 49, 48, 50, 48, 48, 48, 51, + 51, 51, 51, 51, 51, 53, 52, 54, 54, 55, + 55, 56, 56, 56, 56, 58, 57, 60, 59, 61, + 61, 63, 62, 64, 64, 65, 65, 65, 65, 66, + 67, 68, 69, 69, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 71, 72, 74, 73, 75, 75, 75, + 76, 76, 76, 77, 78, 78, 78, 78, 78, 78, + 78, 78, 79, 79, 79, 79, 79, 79, 79, 80, + 81, 81, 81, 81, 81, 81, 81, 82, 82, 82, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 84, 84, 84, 84, 85, 85, + 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 1, 0, 4, 0, 4, 1, 0, 1, + 1, 1, 1, 1, 1, 0, 5, 2, 2, 3, + 1, 1, 1, 3, 0, 0, 6, 0, 7, 1, + 3, 0, 5, 2, 2, 3, 3, 1, 0, 1, + 3, 2, 1, 1, 0, 1, 3, 2, 4, 2, + 4, 1, 1, 1, 1, 0, 5, 2, 2, 2, + 3, 1, 0, 1, 3, 5, 5, 3, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 1, 3, 4, + 2, 5, 3, 4, 2, 1, 1, 3, 1, 3, + 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 4, 3, 4, 2, 6, 3, + 1, 2, 3, 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 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 7, 13, 15, 9, 12, 10, 31, 11, 55, 14, + 5, 59, 114, 113, 115, 116, 117, 118, 120, 119, + 121, 122, 124, 125, 126, 57, 127, 123, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 58, 25, + 33, 34, 0, 86, 90, 91, 93, 95, 99, 98, + 97, 100, 0, 0, 110, 0, 0, 0, 85, 88, + 101, 102, 103, 17, 18, 1, 0, 0, 0, 0, + 0, 0, 0, 107, 0, 0, 111, 92, 94, 96, + 0, 80, 0, 84, 0, 0, 0, 24, 0, 0, + 6, 0, 27, 105, 0, 109, 0, 77, 72, 73, + 75, 76, 74, 79, 0, 0, 0, 82, 89, 87, + 112, 4, 21, 0, 20, 22, 0, 43, 0, 37, + 39, 0, 0, 42, 0, 0, 0, 0, 61, 63, + 71, 0, 0, 106, 104, 0, 0, 0, 83, 0, + 16, 24, 0, 32, 0, 54, 53, 0, 0, 0, + 45, 41, 68, 69, 0, 0, 70, 56, 0, 26, + 29, 0, 0, 78, 81, 23, 19, 36, 35, 0, + 40, 49, 47, 64, 67, 60, 0, 28, 108, 0, + 0, 46, 0, 0, 30, 50, 48, 65, 66 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 8, 9, 76, 80, 10, 11, 77, 12, 123, + 124, 13, 81, 14, 142, 171, 15, 78, 16, 128, + 129, 130, 131, 132, 157, 158, 159, 17, 79, 18, + 137, 138, 139, 113, 19, 140, 68, 69, 70, 71, + 72, 125 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -146 +static const yytype_int16 yypact[] = +{ + 145, -22, 286, 20, 445, 16, 372, 475, 42, -146, + 26, -146, -146, -146, -146, -146, -146, -146, -146, -146, + -146, -146, -146, -146, -146, -146, -146, -146, -146, -146, + -146, -146, -146, -146, -146, -146, -146, -146, -146, -146, + -146, -146, -146, -146, -146, -146, -146, -146, -146, -146, + -146, -146, 11, -146, -146, -146, -146, -146, -146, -146, + -146, -146, 7, 2, -146, 37, 51, 23, 182, 19, + -146, -146, 35, -146, -146, -146, 31, 32, 33, 49, + 102, 66, -2, -146, 386, 415, -146, -146, -146, -146, + 153, -5, 69, -146, 8, 87, 102, 505, 252, 220, + -146, 120, -146, -146, 5, -146, 29, 78, -146, -146, + -146, -146, -146, -146, 79, 86, 88, -146, -146, -146, + -146, -146, 75, 80, 83, -146, 81, -146, 90, 93, + -146, 12, 112, -146, 372, 372, 314, 98, 103, -146, + -146, 107, 122, -146, -146, 533, 127, 108, -146, 153, + -146, 505, 252, -146, 252, -146, -146, 15, 68, 82, + -146, -146, -146, -146, 372, 372, -146, -146, 220, -146, + -146, -26, 109, 118, -146, -146, -146, -146, -146, 343, + -146, -146, -146, 117, 119, -146, 146, -146, -146, 372, + 372, -146, 153, 153, -146, -146, -146, -146, -146 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = +{ + -146, -146, -65, -146, -146, -146, -146, -146, -146, 13, + -146, -146, -146, -146, -146, -146, -146, -146, -146, -109, + -146, -146, -146, -146, -146, -17, -13, -146, -146, -146, + -1, -146, -146, -145, -146, -6, -82, -146, -146, -146, + -51, 3 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -113 +static const yytype_int16 yytable[] = +{ + 67, 82, 104, 106, 175, 48, 143, 51, 83, 118, + 74, 186, 20, 53, 187, 100, 133, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 95, 64, 64, + 155, 121, 119, 156, 115, 102, 141, 49, 116, 114, + 65, 65, 75, 177, 66, 178, 85, 197, 198, -44, + 144, 84, 179, -44, 86, 52, 180, 87, 88, 89, + -3, 90, 94, 172, 95, 96, 145, 97, 98, 53, + 133, 93, 133, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 53, 99, 64, 117, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 65, 114, 64, + 66, 101, -8, 1, 120, -52, 2, -110, 146, -52, + 147, 65, 148, 149, 66, 152, 150, 3, 4, -51, + 151, 1, 5, -51, 2, 160, 153, 154, 162, 163, + 166, 161, 6, 7, 167, 3, 4, 168, -8, 170, + 5, 114, 114, 169, 173, -8, 1, -112, 174, 2, + 6, 7, 181, 182, 188, 192, -8, 193, 183, 184, + 3, 4, 189, 194, 176, 5, 190, 185, 0, 0, + 107, 0, 0, 191, 0, 6, 7, 108, 109, 110, + 111, 112, 65, 195, 196, 22, 23, 24, 25, 26, + 27, 28, 29, 0, 30, 31, 32, 33, 34, 91, + 36, 0, 37, 0, 38, 39, 40, 41, 42, 43, + 44, 0, 45, 46, 47, 0, 0, 0, 0, 0, + 0, 53, 0, 0, 92, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 0, 0, 64, 0, 0, + 0, 0, 134, 135, 136, 0, 0, 0, 0, 65, + 0, 0, 66, 126, 0, 127, -62, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 65, 0, 0, 66, 0, 0, 21, -38, 22, + 23, 24, 25, 26, 27, 28, 29, 0, 30, 31, + 32, 33, 34, 35, 36, 0, 37, 0, 38, 39, + 40, 41, 42, 43, 44, 53, 45, 46, 47, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, + 0, 64, 0, 0, 0, 0, 164, 165, 0, 0, + 0, 0, 0, 65, 53, 0, 66, 0, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 0, 0, + 64, 155, 0, 0, 156, 0, 0, 0, 0, 0, + 0, 0, 65, 53, 0, 66, 0, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 103, 0, 64, + 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 65, 0, 64, 66, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 65, 105, 0, 66, 0, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 65, 0, 0, 66, 22, 23, + 24, 25, 26, 27, 28, 29, 0, 30, 31, 32, + 33, 34, 50, 36, 0, 37, 0, 38, 39, 40, + 41, 42, 43, 44, 0, 45, 46, 47, 22, 23, + 24, 25, 26, 27, 28, 29, 0, 30, 31, 32, + 33, 34, 73, 36, 0, 37, 0, 38, 39, 40, + 41, 42, 43, 44, 0, 45, 46, 47, 22, 23, + 24, 25, 26, 27, 28, 29, 0, 30, 31, 32, + 33, 34, 122, 36, 0, 37, 0, 38, 39, 40, + 41, 42, 43, 44, 0, 45, 46, 47, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 0, 0, + 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 65, 0, 0, 66 +}; + +static const yytype_int16 yycheck[] = +{ + 6, 52, 84, 85, 149, 2, 1, 4, 1, 1, + 7, 37, 34, 1, 40, 80, 98, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 29, 17, 17, + 18, 96, 24, 21, 39, 37, 101, 17, 43, 90, + 29, 29, 0, 152, 32, 154, 44, 192, 193, 37, + 45, 44, 37, 41, 17, 39, 41, 6, 7, 8, + 34, 38, 43, 145, 29, 34, 37, 35, 35, 1, + 152, 68, 154, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 1, 35, 17, 17, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 29, 149, 17, + 32, 35, 0, 1, 17, 37, 4, 29, 29, 41, + 24, 29, 24, 38, 32, 34, 36, 15, 16, 37, + 37, 1, 20, 41, 4, 131, 36, 34, 134, 135, + 136, 19, 30, 31, 36, 15, 16, 34, 36, 17, + 20, 192, 193, 36, 17, 0, 1, 29, 40, 4, + 30, 31, 158, 159, 45, 38, 36, 38, 164, 165, + 15, 16, 179, 17, 151, 20, 179, 168, -1, -1, + 17, -1, -1, 179, -1, 30, 31, 24, 25, 26, + 27, 28, 29, 189, 190, 3, 4, 5, 6, 7, + 8, 9, 10, -1, 12, 13, 14, 15, 16, 17, + 18, -1, 20, -1, 22, 23, 24, 25, 26, 27, + 28, -1, 30, 31, 32, -1, -1, -1, -1, -1, + -1, 1, -1, -1, 42, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, -1, -1, 17, -1, -1, + -1, -1, 22, 23, 24, -1, -1, -1, -1, 29, + -1, -1, 32, 1, -1, 3, 36, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, -1, -1, 17, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 29, -1, -1, 32, -1, -1, 1, 36, 3, + 4, 5, 6, 7, 8, 9, 10, -1, 12, 13, + 14, 15, 16, 17, 18, -1, 20, -1, 22, 23, + 24, 25, 26, 27, 28, 1, 30, 31, 32, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, + -1, 17, -1, -1, -1, -1, 22, 23, -1, -1, + -1, -1, -1, 29, 1, -1, 32, -1, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, -1, -1, + 17, 18, -1, -1, 21, -1, -1, -1, -1, -1, + -1, -1, 29, 1, -1, 32, -1, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 1, -1, 17, + -1, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 29, -1, 17, 32, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 29, 1, -1, 32, -1, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 29, -1, -1, 32, 3, 4, + 5, 6, 7, 8, 9, 10, -1, 12, 13, 14, + 15, 16, 17, 18, -1, 20, -1, 22, 23, 24, + 25, 26, 27, 28, -1, 30, 31, 32, 3, 4, + 5, 6, 7, 8, 9, 10, -1, 12, 13, 14, + 15, 16, 17, 18, -1, 20, -1, 22, 23, 24, + 25, 26, 27, 28, -1, 30, 31, 32, 3, 4, + 5, 6, 7, 8, 9, 10, -1, 12, 13, 14, + 15, 16, 17, 18, -1, 20, -1, 22, 23, 24, + 25, 26, 27, 28, -1, 30, 31, 32, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, -1, -1, + 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 29, -1, -1, 32 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 1, 4, 15, 16, 20, 30, 31, 47, 48, + 51, 52, 54, 57, 59, 62, 64, 73, 75, 80, + 34, 1, 3, 4, 5, 6, 7, 8, 9, 10, + 12, 13, 14, 15, 16, 17, 18, 20, 22, 23, + 24, 25, 26, 27, 28, 30, 31, 32, 87, 17, + 17, 87, 39, 1, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 17, 29, 32, 81, 82, 83, + 84, 85, 86, 17, 87, 0, 49, 53, 63, 74, + 50, 58, 86, 1, 44, 44, 17, 6, 7, 8, + 38, 17, 42, 87, 43, 29, 34, 35, 35, 35, + 48, 35, 37, 1, 82, 1, 82, 17, 24, 25, + 26, 27, 28, 79, 86, 39, 43, 17, 1, 24, + 17, 48, 17, 55, 56, 87, 1, 3, 65, 66, + 67, 68, 69, 82, 22, 23, 24, 76, 77, 78, + 81, 48, 60, 1, 45, 37, 29, 24, 24, 38, + 36, 37, 34, 36, 34, 18, 21, 70, 71, 72, + 81, 19, 81, 81, 22, 23, 81, 36, 34, 36, + 17, 61, 82, 17, 40, 79, 55, 65, 65, 37, + 41, 81, 81, 81, 81, 76, 37, 40, 45, 71, + 72, 81, 38, 38, 17, 81, 81, 79, 79 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) +#else +static void +yy_stack_print (bottom, top) + yytype_int16 *bottom; + yytype_int16 *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule) +#else +static void +yy_reduce_print (yyvsp, yyrule) + YYSTYPE *yyvsp; + int yyrule; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + fprintf (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + fprintf (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + YYUSE (yyvaluep); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + +/* The look-ahead symbol. */ +int yychar; + +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + + int yystate; + int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ + int yytoken = 0; +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp; + + + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + look-ahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to look-ahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a look-ahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 3: +#line 75 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 5: +#line 79 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + yyerrok; +;} + break; + + case 7: +#line 84 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + g_parse->error("`;' missing after definition"); +;} + break; + + case 8: +#line 88 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 9: +#line 96 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + assert((yyvsp[(1) - (1)]) == 0 || NamespacePtr::dynamicCast((yyvsp[(1) - (1)]))); +;} + break; + + case 10: +#line 100 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + assert((yyvsp[(1) - (1)]) == 0 || InterfacePtr::dynamicCast((yyvsp[(1) - (1)]))); +;} + break; + + case 11: +#line 104 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + assert((yyvsp[(1) - (1)]) == 0 || StructPtr::dynamicCast((yyvsp[(1) - (1)]))); +;} + break; + + case 12: +#line 108 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 13: +#line 111 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + assert((yyvsp[(1) - (1)]) == 0 || EnumPtr::dynamicCast((yyvsp[(1) - (1)]))); +;} + break; + + case 14: +#line 115 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + assert((yyvsp[(1) - (1)]) == 0 || ConstPtr::dynamicCast((yyvsp[(1) - (1)]))); +;} + break; + + case 15: +#line 124 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = (yyvsp[(1) - (1)]); +;} + break; + + case 16: +#line 128 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + if((yyvsp[(3) - (5)])) + { + g_parse->popContainer(); + (yyval) = (yyvsp[(3) - (5)]); + } + else + { + (yyval) = 0; + } + + (yyval) = (yyvsp[(2) - (5)]); +;} + break; + + case 17: +#line 147 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + NamespacePtr c = NamespacePtr::dynamicCast(g_parse->currentContainer()); + if(!c) + { + g_parse->error("enum must define in namespace"); + } + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (2)])); + EnumPtr e = c->createEnum(ident->v); + g_parse->pushContainer(e); + + (yyval) = e; +;} + break; + + case 18: +#line 160 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (2)])); + g_parse->error("keyword `" + ident->v + "' cannot be used as enumeration name"); + (yyval) = (yyvsp[(2) - (2)]); +;} + break; + + case 19: +#line 171 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = (yyvsp[(2) - (3)]); +;} + break; + + case 20: +#line 175 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 21: +#line 183 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + TypePtr type = TypePtr::dynamicCast(g_parse->createBuiltin(Builtin::KindLong)); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); + TypeIdPtr tPtr = new TypeId(type, ident->v); + tPtr->disableDefault(); + EnumPtr e = EnumPtr::dynamicCast(g_parse->currentContainer()); + assert(e); + e->addMember(tPtr); + (yyval) = e; +;} + break; + + case 22: +#line 194 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); + g_parse->error("keyword `" + ident->v + "' cannot be used as enumerator"); +;} + break; + + case 23: +#line 199 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + TypePtr type = TypePtr::dynamicCast(g_parse->createBuiltin(Builtin::KindLong)); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (3)])); + TypeIdPtr tPtr = new TypeId(type, ident->v); + ConstGrammarPtr sPtr = ConstGrammarPtr::dynamicCast((yyvsp[(3) - (3)])); + g_parse->checkConstValue(tPtr, sPtr->t); + tPtr->setDefault(sPtr->v); + EnumPtr e = EnumPtr::dynamicCast(g_parse->currentContainer()); + assert(e); + e->addMember(tPtr); + (yyval) = e; +;} + break; + + case 24: +#line 212 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 25: +#line 220 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (2)])); + ContainerPtr c = g_parse->currentContainer(); + NamespacePtr n = c->createNamespace(ident->v); + if(n) + { + g_parse->pushContainer(n); + (yyval) = GrammarBasePtr::dynamicCast(n); + } + else + { + (yyval) = 0; + } +;} + break; + + case 26: +#line 235 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + if((yyvsp[(3) - (6)])) + { + g_parse->popContainer(); + (yyval) = (yyvsp[(3) - (6)]); + } + else + { + (yyval) = 0; + } +;} + break; + + case 27: +#line 253 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(3) - (4)])); + StructPtr sp = StructPtr::dynamicCast(g_parse->findUserType(ident->v)); + if(!sp) + { + g_parse->error("struct '" + ident->v + "' undefined!"); + } + + g_parse->setKeyStruct(sp); +;} + break; + + case 28: +#line 264 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 29: +#line 272 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); + StructPtr np = g_parse->getKeyStruct(); + if(np) + { + np->addKey(ident->v); + } + else + { + (yyval) = 0; + } +;} + break; + + case 30: +#line 285 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(3) - (3)])); + StructPtr np = g_parse->getKeyStruct(); + if(np) + { + np->addKey(ident->v); + } + else + { + (yyval) = 0; + } +;} + break; + + case 31: +#line 304 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); + + NamespacePtr c = NamespacePtr::dynamicCast(g_parse->currentContainer()); + + InterfacePtr cl = c->createInterface(ident->v); + if(cl) + { + g_parse->pushContainer(cl); + (yyval) = GrammarBasePtr::dynamicCast(cl); + } + else + { + (yyval) = 0; + } +;} + break; + + case 32: +#line 321 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + if((yyvsp[(2) - (5)])) + { + g_parse->popContainer(); + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[(2) - (5)])); + } + else + { + (yyval) = 0; + } +;} + break; + + case 33: +#line 338 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = (yyvsp[(2) - (2)]); +;} + break; + + case 34: +#line 342 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (2)])); + g_parse->error("keyword `" + ident->v + "' cannot be used as interface name"); + (yyval) = (yyvsp[(2) - (2)]); +;} + break; + + case 35: +#line 353 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 36: +#line 356 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 37: +#line 359 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + g_parse->error("`;' missing after definition"); +;} + break; + + case 38: +#line 363 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 40: +#line 377 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + if((yyvsp[(1) - (3)])) + { + g_parse->popContainer(); + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[(1) - (3)])); + } + else + { + (yyval) = 0; + } +;} + break; + + case 41: +#line 394 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + TypePtr returnType = TypePtr::dynamicCast((yyvsp[(1) - (2)])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (2)])); + string name = ident->v; + InterfacePtr cl = InterfacePtr::dynamicCast(g_parse->currentContainer()); + if(cl) + { + OperationPtr op = cl->createOperation(name, returnType); + if(op) + { + g_parse->pushContainer(op); + (yyval) = GrammarBasePtr::dynamicCast(op); + } + else + { + (yyval) = 0; + } + } + else + { + (yyval) = 0; + } +;} + break; + + case 43: +#line 424 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = 0; +;} + break; + + case 44: +#line 434 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 45: +#line 437 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[(1) - (1)])); + + OperationPtr op = OperationPtr::dynamicCast(g_parse->currentContainer()); + assert(op); + if(op) + { + op->createParamDecl(tsp, false, false); + } +;} + break; + + case 46: +#line 448 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[(3) - (3)])); + + OperationPtr op = OperationPtr::dynamicCast(g_parse->currentContainer()); + assert(op); + if(op) + { + op->createParamDecl(tsp, false, false); + } +;} + break; + + case 47: +#line 459 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + BoolGrammarPtr isOutParam = BoolGrammarPtr::dynamicCast((yyvsp[(1) - (2)])); + TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[(2) - (2)])); + + OperationPtr op = OperationPtr::dynamicCast(g_parse->currentContainer()); + assert(op); + if(op) + { + op->createParamDecl(tsp, isOutParam->v, false); + } +;} + break; + + case 48: +#line 471 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + BoolGrammarPtr isOutParam = BoolGrammarPtr::dynamicCast((yyvsp[(3) - (4)])); + TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[(4) - (4)])); + + OperationPtr op = OperationPtr::dynamicCast(g_parse->currentContainer()); + assert(op); + if(op) + { + op->createParamDecl(tsp, isOutParam->v, false); + } +;} + break; + + case 49: +#line 483 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + BoolGrammarPtr isRouteKeyParam = BoolGrammarPtr::dynamicCast((yyvsp[(1) - (2)])); + TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[(2) - (2)])); + + OperationPtr op = OperationPtr::dynamicCast(g_parse->currentContainer()); + assert(op); + if(op) + { + op->createParamDecl(tsp, false, isRouteKeyParam->v); + } +;} + break; + + case 50: +#line 495 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + BoolGrammarPtr isRouteKeyParam = BoolGrammarPtr::dynamicCast((yyvsp[(3) - (4)])); + TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[(4) - (4)])); + + OperationPtr op = OperationPtr::dynamicCast(g_parse->currentContainer()); + assert(op); + if(op) + { + op->createParamDecl(tsp, false, isRouteKeyParam->v); + } +;} + break; + + case 51: +#line 507 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + g_parse->error("'out' must be defined with a type"); +;} + break; + + case 52: +#line 511 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + g_parse->error("'routekey' must be defined with a type"); +;} + break; + + case 53: +#line 520 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + BoolGrammarPtr routekey = new BoolGrammar; + routekey->v = true; + (yyval) = GrammarBasePtr::dynamicCast(routekey); +;} + break; + + case 54: +#line 531 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + BoolGrammarPtr out = new BoolGrammar; + out->v = true; + (yyval) = GrammarBasePtr::dynamicCast(out); +;} + break; + + case 55: +#line 542 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); + NamespacePtr np = NamespacePtr::dynamicCast(g_parse->currentContainer()); + if(np) + { + StructPtr sp = np->createStruct(ident->v); + if(sp) + { + g_parse->pushContainer(sp); + (yyval) = GrammarBasePtr::dynamicCast(sp); + } + else + { + (yyval) = 0; + } + } + else + { + g_parse->error("struct '" + ident->v + "' must definition in namespace"); + } +;} + break; + + case 56: +#line 564 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + if((yyvsp[(2) - (5)])) + { + g_parse->popContainer(); + } + (yyval) = (yyvsp[(2) - (5)]); + + StructPtr st = StructPtr::dynamicCast((yyval)); + assert(st); + if(st->getAllMemberPtr().size() == 0) + { + g_parse->error("struct `" + st->getSid() + "' must have at least one member"); + } +;} + break; + + case 57: +#line 584 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = (yyvsp[(2) - (2)]); +;} + break; + + case 58: +#line 588 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (2)])); + + g_parse->error("keyword `" + ident->v + "' cannot be used as struct name"); +;} + break; + + case 59: +#line 594 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + g_parse->error("abstract declarator '' used as declaration"); +;} + break; + + case 60: +#line 603 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + +;} + break; + + case 61: +#line 607 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + g_parse->error("';' missing after definition"); +;} + break; + + case 62: +#line 611 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 63: +#line 621 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[(1) - (1)])); +;} + break; + + case 64: +#line 630 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StructPtr np = StructPtr::dynamicCast(g_parse->currentContainer()); + if(np) + { + IntergerGrammarPtr iPtr = IntergerGrammarPtr::dynamicCast((yyvsp[(1) - (3)])); + g_parse->checkTag(iPtr->v); + + TypeIdPtr tPtr = TypeIdPtr::dynamicCast((yyvsp[(3) - (3)])); + tPtr->setRequire(iPtr->v); + np->addTypeId(tPtr); + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[(3) - (3)])); + } + else + { + (yyval) = 0; + } +;} + break; + + case 65: +#line 648 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StructPtr np = StructPtr::dynamicCast(g_parse->currentContainer()); + if(np) + { + IntergerGrammarPtr iPtr = IntergerGrammarPtr::dynamicCast((yyvsp[(1) - (5)])); + g_parse->checkTag(iPtr->v); + + TypeIdPtr tPtr = TypeIdPtr::dynamicCast((yyvsp[(3) - (5)])); + ConstGrammarPtr sPtr = ConstGrammarPtr::dynamicCast((yyvsp[(5) - (5)])); + g_parse->checkConstValue(tPtr, sPtr->t); + + tPtr->setRequire(iPtr->v); + tPtr->setDefault(sPtr->v); + np->addTypeId(tPtr); + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[(3) - (5)])); + } + else + { + (yyval) = 0; + } +;} + break; + + case 66: +#line 670 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StructPtr np = StructPtr::dynamicCast(g_parse->currentContainer()); + if(np) + { + IntergerGrammarPtr iPtr = IntergerGrammarPtr::dynamicCast((yyvsp[(1) - (5)])); + g_parse->checkTag(iPtr->v); + + TypeIdPtr tPtr = TypeIdPtr::dynamicCast((yyvsp[(3) - (5)])); + ConstGrammarPtr sPtr = ConstGrammarPtr::dynamicCast((yyvsp[(5) - (5)])); + g_parse->checkConstValue(tPtr, sPtr->t); + + tPtr->setOptional(iPtr->v); + tPtr->setDefault(sPtr->v); + np->addTypeId(tPtr); + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[(3) - (5)])); + } + else + { + (yyval) = 0; + } +;} + break; + + case 67: +#line 692 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StructPtr np = StructPtr::dynamicCast(g_parse->currentContainer()); + if(np) + { + IntergerGrammarPtr iPtr = IntergerGrammarPtr::dynamicCast((yyvsp[(1) - (3)])); + g_parse->checkTag(iPtr->v); + TypeIdPtr tPtr = TypeIdPtr::dynamicCast((yyvsp[(3) - (3)])); + tPtr->setOptional(iPtr->v); + np->addTypeId(tPtr); + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[(3) - (3)])); + } + else + { + (yyval) = 0; + } +;} + break; + + case 68: +#line 709 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + g_parse->error("struct member need 'tag'"); +;} + break; + + case 69: +#line 713 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + g_parse->error("struct member need 'tag'"); +;} + break; + + case 70: +#line 717 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + g_parse->error("struct member need 'require' or 'optional'"); +;} + break; + + case 71: +#line 721 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + g_parse->error("struct member need 'tag' or 'require' or 'optional'"); +;} + break; + + case 72: +#line 730 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + IntergerGrammarPtr intVal = IntergerGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); + ostringstream sstr; + sstr << intVal->v; + ConstGrammarPtr c = new ConstGrammar(); + c->t = ConstGrammar::VALUE; + c->v = sstr.str(); + (yyval) = c; +;} + break; + + case 73: +#line 740 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + FloatGrammarPtr floatVal = FloatGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); + ostringstream sstr; + sstr << floatVal->v; + ConstGrammarPtr c = new ConstGrammar(); + c->t = ConstGrammar::VALUE; + c->v = sstr.str(); + (yyval) = c; +;} + break; + + case 74: +#line 750 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); + ConstGrammarPtr c = new ConstGrammar(); + c->t = ConstGrammar::STRING; + c->v = ident->v; + (yyval) = c; +;} + break; + + case 75: +#line 758 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); + ConstGrammarPtr c = new ConstGrammar(); + c->t = ConstGrammar::BOOL; + c->v = ident->v; + (yyval) = c; +;} + break; + + case 76: +#line 766 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); + ConstGrammarPtr c = new ConstGrammar(); + c->t = ConstGrammar::BOOL; + c->v = ident->v; + (yyval) = c; +;} + break; + + case 77: +#line 774 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); + + if (g_parse->checkEnum(ident->v) == false) + { + g_parse->error("error enum default value, not defined yet"); + } + ConstGrammarPtr c = new ConstGrammar(); + c->t = ConstGrammar::ENUM; + c->v = ident->v; + (yyval) = c; +;} + break; + + case 78: +#line 787 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + + StringGrammarPtr scoped = StringGrammarPtr::dynamicCast((yyvsp[(1) - (3)])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(3) - (3)])); + + if (g_parse->checkEnum(ident->v) == false) + { + g_parse->error("error enum default value, not defined yet"); + } + ConstGrammarPtr c = new ConstGrammar(); + c->t = ConstGrammar::ENUM; + c->v = scoped->v + "::" + ident->v; + (yyval) = c; +;} + break; + + case 79: +#line 807 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + NamespacePtr np = NamespacePtr::dynamicCast(g_parse->currentContainer()); + if(!np) + { + g_parse->error("const type must define in namespace"); + } + + TypeIdPtr t = TypeIdPtr::dynamicCast((yyvsp[(2) - (4)])); + ConstGrammarPtr c = ConstGrammarPtr::dynamicCast((yyvsp[(4) - (4)])); + ConstPtr cPtr = np->createConst(t, c); + (yyval) = cPtr; +;} + break; + + case 80: +#line 825 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + TypePtr type = TypePtr::dynamicCast((yyvsp[(1) - (2)])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (2)])); + + TypeIdPtr typeIdPtr = new TypeId(type, ident->v); + + (yyval) = GrammarBasePtr::dynamicCast(typeIdPtr); +;} + break; + + case 81: +#line 834 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + TypePtr type = g_parse->createVector(TypePtr::dynamicCast((yyvsp[(1) - (5)]))); + IntergerGrammarPtr iPtrSize = IntergerGrammarPtr::dynamicCast((yyvsp[(4) - (5)])); + g_parse->checkArrayVaid(type,iPtrSize->v); + type->setArray(iPtrSize->v); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (5)])); + TypeIdPtr typeIdPtr = new TypeId(type, ident->v); + (yyval) = GrammarBasePtr::dynamicCast(typeIdPtr); +;} + break; + + case 82: +#line 844 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + TypePtr type = g_parse->createVector(TypePtr::dynamicCast((yyvsp[(1) - (3)]))); + //IntergerGrammarPtr iPtrSize = IntergerGrammarPtr::dynamicCast($4); + g_parse->checkPointerVaid(type); + type->setPointer(true); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(3) - (3)])); + TypeIdPtr typeIdPtr = new TypeId(type, ident->v); + (yyval) = GrammarBasePtr::dynamicCast(typeIdPtr); +;} + break; + + case 83: +#line 854 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + TypePtr type = TypePtr::dynamicCast((yyvsp[(1) - (4)])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (4)])); + TypeIdPtr typeIdPtr = new TypeId(type, ident->v); + IntergerGrammarPtr iPtrSize = IntergerGrammarPtr::dynamicCast((yyvsp[(3) - (4)])); + g_parse->checkArrayVaid(type,iPtrSize->v); + (yyval) = GrammarBasePtr::dynamicCast(typeIdPtr); +;} + break; + + case 84: +#line 863 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (2)])); + g_parse->error("keyword `" + ident->v + "' cannot be used as data member name"); +;} + break; + + case 85: +#line 868 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + g_parse->error("missing data member name"); +;} + break; + + case 86: +#line 872 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + g_parse->error("unkown type"); +;} + break; + + case 87: +#line 881 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + + TypePtr type = TypePtr::dynamicCast((yyvsp[(1) - (3)])); + IntergerGrammarPtr iPtrSize = IntergerGrammarPtr::dynamicCast((yyvsp[(3) - (3)])); + g_parse->checkArrayVaid(type,iPtrSize->v); + type->setArray(iPtrSize->v); + (yyval) = type; +;} + break; + + case 88: +#line 890 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = (yyvsp[(1) - (1)]); +;} + break; + + case 89: +#line 894 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + g_parse->error("array missing size"); +;} + break; + + case 90: +#line 903 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = g_parse->createBuiltin(Builtin::KindBool); +;} + break; + + case 91: +#line 907 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = g_parse->createBuiltin(Builtin::KindByte); +;} + break; + + case 92: +#line 911 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = g_parse->createBuiltin(Builtin::KindShort,true); +;} + break; + + case 93: +#line 915 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = g_parse->createBuiltin(Builtin::KindShort); +;} + break; + + case 94: +#line 919 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = g_parse->createBuiltin(Builtin::KindInt,true); +;} + break; + + case 95: +#line 923 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = g_parse->createBuiltin(Builtin::KindInt); +;} + break; + + case 96: +#line 927 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = g_parse->createBuiltin(Builtin::KindLong,true); +;} + break; + + case 97: +#line 931 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = g_parse->createBuiltin(Builtin::KindLong); +;} + break; + + case 98: +#line 935 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = g_parse->createBuiltin(Builtin::KindFloat); +;} + break; + + case 99: +#line 939 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = g_parse->createBuiltin(Builtin::KindDouble); +;} + break; + + case 100: +#line 943 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = g_parse->createBuiltin(Builtin::KindString); +;} + break; + + case 101: +#line 947 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[(1) - (1)])); +;} + break; + + case 102: +#line 951 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[(1) - (1)])); +;} + break; + + case 103: +#line 955 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); + TypePtr sp = g_parse->findUserType(ident->v); + if(sp) + { + (yyval) = GrammarBasePtr::dynamicCast(sp); + } + else + { + g_parse->error("'" + ident->v + "' undefined!"); + } +;} + break; + + case 104: +#line 973 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = GrammarBasePtr::dynamicCast(g_parse->createVector(TypePtr::dynamicCast((yyvsp[(3) - (4)])))); +;} + break; + + case 105: +#line 977 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + g_parse->error("vector error"); +;} + break; + + case 106: +#line 981 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + g_parse->error("vector missing '>'"); +;} + break; + + case 107: +#line 985 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + g_parse->error("vector missing type"); +;} + break; + + case 108: +#line 994 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + (yyval) = GrammarBasePtr::dynamicCast(g_parse->createMap(TypePtr::dynamicCast((yyvsp[(3) - (6)])), TypePtr::dynamicCast((yyvsp[(5) - (6)])))); +;} + break; + + case 109: +#line 998 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + g_parse->error("map error"); +;} + break; + + case 110: +#line 1007 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 111: +#line 1010 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (2)])); + ident->v = "::" + ident->v; + (yyval) = GrammarBasePtr::dynamicCast(ident); +;} + break; + + case 112: +#line 1016 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { + StringGrammarPtr scoped = StringGrammarPtr::dynamicCast((yyvsp[(1) - (3)])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(3) - (3)])); + scoped->v += "::"; + scoped->v += ident->v; + (yyval) = GrammarBasePtr::dynamicCast(scoped); +;} + break; + + case 113: +#line 1029 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 114: +#line 1032 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 115: +#line 1035 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 116: +#line 1038 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 117: +#line 1041 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 118: +#line 1044 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 119: +#line 1047 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 120: +#line 1050 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 121: +#line 1053 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 122: +#line 1056 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 123: +#line 1059 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 124: +#line 1062 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 125: +#line 1065 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 126: +#line 1068 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 127: +#line 1071 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 128: +#line 1074 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 129: +#line 1077 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 130: +#line 1080 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 131: +#line 1083 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 132: +#line 1086 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 133: +#line 1089 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 134: +#line 1092 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 135: +#line 1095 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 136: +#line 1098 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + case 137: +#line 1101 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + { +;} + break; + + +/* Line 1267 of yacc.c. */ +#line 2907 "tars.tab.cpp" + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse look-ahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse look-ahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + +#line 1105 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + + + + diff --git a/tools/tarsparse/CMakeLists.txt b/tools/tarsparse/CMakeLists.txt index 9bc2c9417dea44a975af4b379fdaf595a195021a..b47e3170dc8c7c5bd8054274641deba0e9fa5e63 100644 --- a/tools/tarsparse/CMakeLists.txt +++ b/tools/tarsparse/CMakeLists.txt @@ -8,11 +8,9 @@ aux_source_directory(. DIR_SRCS) set(DEPENDS_SRC_LIST) set(DEPENDS_LEC_YACC_SRC_LIST) -#if(WIN32) list(APPEND DEPENDS_LEC_YACC_SRC_LIST "tars.lex.cpp") list(APPEND DEPENDS_LEC_YACC_SRC_LIST "tars.tab.hpp") list(APPEND DEPENDS_LEC_YACC_SRC_LIST "tars.tab.cpp") -#endif() set(DEPENDS_LEC_YACC_SRC_DIR "${PROJECT_SOURCE_DIR}/tarsGrammar/") diff --git a/tools/tarsparse/tars.lex.cpp b/tools/tarsparse/tars.lex.cpp index 21dd58d4adf9276cab7b9025ec317f15d5e4c37b..bf257929a309d38ebcc799cb5cf495baa312d5ca 100644 --- a/tools/tarsparse/tars.lex.cpp +++ b/tools/tarsparse/tars.lex.cpp @@ -9,7 +9,7 @@ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 37 +#define YY_FLEX_SUBMINOR_VERSION 35 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif @@ -47,6 +47,7 @@ typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; +typedef uint64_t flex_uint64_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; @@ -54,6 +55,7 @@ typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN @@ -84,8 +86,6 @@ typedef unsigned int flex_uint32_t; #define UINT32_MAX (4294967295U) #endif -#endif /* ! C99 */ - #endif /* ! FLEXINT_H */ #ifdef __cplusplus @@ -176,7 +176,7 @@ extern FILE *yyin, *yyout; */ #define YY_LESS_LINENO(n) \ do { \ - int yyl;\ + yy_size_t yyl;\ for ( yyl = n; yyl < yyleng; ++yyl )\ if ( yytext[yyl] == '\n' )\ --yylineno;\ @@ -369,7 +369,7 @@ static void yy_fatal_error (yyconst char msg[] ); */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ - yyleng = (size_t) (yy_cp - yy_bp); \ + yyleng = (yy_size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; @@ -513,7 +513,7 @@ int yy_flex_debug = 0; #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; -#line 1 "/home/tars/TarsCpp/tools/tarsgrammar/tars.l" +#line 1 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l" /** * Tencent is pleased to support the open source community by making Tars available. * @@ -529,7 +529,7 @@ char *yytext; * CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -#line 20 "/home/tars/TarsCpp/tools/tarsgrammar/tars.l" +#line 20 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l" #include #include #include @@ -649,7 +649,7 @@ static int input (void ); /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ -#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) +#define ECHO fwrite( yytext, yyleng, 1, yyout ) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, @@ -660,7 +660,7 @@ static int input (void ); if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ - size_t n; \ + yy_size_t n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -742,7 +742,7 @@ YY_DECL register char *yy_cp, *yy_bp; register int yy_act; -#line 67 "/home/tars/TarsCpp/tools/tarsgrammar/tars.l" +#line 67 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l" #line 749 "tars.lex.cpp" @@ -840,12 +840,12 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 69 "/home/tars/TarsCpp/tools/tarsgrammar/tars.l" +#line 69 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l" { BEGIN(INCL); } YY_BREAK case 2: YY_RULE_SETUP -#line 71 "/home/tars/TarsCpp/tools/tarsgrammar/tars.l" +#line 71 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l" { if ( include_file_stack_ptr >= MAX_INCLUDE_DEPTH ) { @@ -878,7 +878,7 @@ YY_RULE_SETUP YY_BREAK case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(INCL): -#line 101 "/home/tars/TarsCpp/tools/tarsgrammar/tars.l" +#line 101 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l" { --include_file_stack_ptr; if ( include_file_stack_ptr < 0 ) @@ -897,14 +897,14 @@ case YY_STATE_EOF(INCL): YY_BREAK case 3: YY_RULE_SETUP -#line 117 "/home/tars/TarsCpp/tools/tarsgrammar/tars.l" +#line 117 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l" { return TARS_SCOPE_DELIMITER; } YY_BREAK case 4: YY_RULE_SETUP -#line 121 "/home/tars/TarsCpp/tools/tarsgrammar/tars.l" +#line 121 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l" { // C++ comment bool e = false; @@ -925,7 +925,7 @@ YY_RULE_SETUP YY_BREAK case 5: YY_RULE_SETUP -#line 139 "/home/tars/TarsCpp/tools/tarsgrammar/tars.l" +#line 139 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l" { // C comment bool e = false; @@ -976,7 +976,7 @@ YY_RULE_SETUP YY_BREAK case 6: YY_RULE_SETUP -#line 187 "/home/tars/TarsCpp/tools/tarsgrammar/tars.l" +#line 187 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l" { StringGrammarPtr ident = new StringGrammar; ident->v = yytext; @@ -987,7 +987,7 @@ YY_RULE_SETUP case 7: /* rule 7 can match eol */ YY_RULE_SETUP -#line 194 "/home/tars/TarsCpp/tools/tarsgrammar/tars.l" +#line 194 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l" { StringGrammarPtr ident = new StringGrammar; ident->v = yytext; @@ -1000,7 +1000,7 @@ YY_RULE_SETUP YY_BREAK case 8: YY_RULE_SETUP -#line 204 "/home/tars/TarsCpp/tools/tarsgrammar/tars.l" +#line 204 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l" { StringGrammarPtr str = new StringGrammar; bool e = false; @@ -1115,7 +1115,7 @@ YY_RULE_SETUP YY_BREAK case 9: YY_RULE_SETUP -#line 316 "/home/tars/TarsCpp/tools/tarsgrammar/tars.l" +#line 316 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l" { errno = 0; IntergerGrammarPtr ptr = new IntergerGrammar; @@ -1140,7 +1140,7 @@ YY_RULE_SETUP YY_BREAK case 10: YY_RULE_SETUP -#line 338 "/home/tars/TarsCpp/tools/tarsgrammar/tars.l" +#line 338 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l" { errno = 0; FloatGrammarPtr ptr = new FloatGrammar; @@ -1175,7 +1175,7 @@ YY_RULE_SETUP case 11: /* rule 11 can match eol */ YY_RULE_SETUP -#line 369 "/home/tars/TarsCpp/tools/tarsgrammar/tars.l" +#line 369 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l" { if(yytext[0] == '\n') { @@ -1185,7 +1185,7 @@ YY_RULE_SETUP YY_BREAK case 12: YY_RULE_SETUP -#line 376 "/home/tars/TarsCpp/tools/tarsgrammar/tars.l" +#line 376 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l" { if(yytext[0] < 32 || yytext[0] > 126) { @@ -1204,7 +1204,7 @@ YY_RULE_SETUP YY_BREAK case 13: YY_RULE_SETUP -#line 392 "/home/tars/TarsCpp/tools/tarsgrammar/tars.l" +#line 392 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l" ECHO; YY_BREAK #line 1211 "tars.lex.cpp" @@ -1398,7 +1398,7 @@ static int yy_get_next_buffer (void) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); @@ -1531,7 +1531,7 @@ static int yy_get_next_buffer (void) yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 51); - return yy_is_jam ? 0 : yy_current_state; + return yy_is_jam ? 0 : yy_current_state; } static void yyunput (int c, register char * yy_bp ) @@ -1623,7 +1623,7 @@ static int yy_get_next_buffer (void) case EOB_ACT_END_OF_FILE: { if ( yywrap( ) ) - return EOF; + return 0; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; @@ -1764,6 +1764,10 @@ static void yy_load_buffer_state (void) yyfree((void *) b ); } +#ifndef __cplusplus +extern int isatty (int ); +#endif /* __cplusplus */ + /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. @@ -1968,8 +1972,8 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) /** Setup the input buffer state to scan the given bytes. The next call to yylex() will * scan from a @e copy of @a bytes. - * @param yybytes the byte buffer to scan - * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ @@ -1977,8 +1981,7 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len { YY_BUFFER_STATE b; char *buf; - yy_size_t n; - yy_size_t i; + yy_size_t n, i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; @@ -2211,7 +2214,7 @@ void yyfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 392 "/home/tars/TarsCpp/tools/tarsgrammar/tars.l" +#line 392 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l" diff --git a/tools/tarsparse/tars.tab.cpp b/tools/tarsparse/tars.tab.cpp index 84f3b9305233ce9ac3a5f25dc7d2c6ce75caec35..3d5e1136b10f2290410445f21591fb762cf7f27e 100644 --- a/tools/tarsparse/tars.tab.cpp +++ b/tools/tarsparse/tars.tab.cpp @@ -1,13 +1,14 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 2.3. */ -/* Bison implementation for Yacc-like parsers in C +/* Skeleton implementation for Bison's Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. - This program is free software: you can redistribute it and/or modify + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + the Free Software Foundation; either version 2, or (at your option) + any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -15,7 +16,9 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . */ + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -44,7 +47,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.0.4" +#define YYBISON_VERSION "2.3" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -52,17 +55,88 @@ /* Pure parsers. */ #define YYPURE 0 -/* Push parsers. */ -#define YYPUSH 0 +/* Using locations. */ +#define YYLSP_NEEDED 0 -/* Pull parsers. */ -#define YYPULL 1 + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + TARS_VOID = 258, + TARS_STRUCT = 259, + TARS_BOOL = 260, + TARS_BYTE = 261, + TARS_SHORT = 262, + TARS_INT = 263, + TARS_DOUBLE = 264, + TARS_FLOAT = 265, + TARS_LONG = 266, + TARS_STRING = 267, + TARS_VECTOR = 268, + TARS_MAP = 269, + TARS_NAMESPACE = 270, + TARS_INTERFACE = 271, + TARS_IDENTIFIER = 272, + TARS_OUT = 273, + TARS_OP = 274, + TARS_KEY = 275, + TARS_ROUTE_KEY = 276, + TARS_REQUIRE = 277, + TARS_OPTIONAL = 278, + TARS_CONST_INTEGER = 279, + TARS_CONST_FLOAT = 280, + TARS_FALSE = 281, + TARS_TRUE = 282, + TARS_STRING_LITERAL = 283, + TARS_SCOPE_DELIMITER = 284, + TARS_CONST = 285, + TARS_ENUM = 286, + TARS_UNSIGNED = 287, + BAD_CHAR = 288 + }; +#endif +/* Tokens. */ +#define TARS_VOID 258 +#define TARS_STRUCT 259 +#define TARS_BOOL 260 +#define TARS_BYTE 261 +#define TARS_SHORT 262 +#define TARS_INT 263 +#define TARS_DOUBLE 264 +#define TARS_FLOAT 265 +#define TARS_LONG 266 +#define TARS_STRING 267 +#define TARS_VECTOR 268 +#define TARS_MAP 269 +#define TARS_NAMESPACE 270 +#define TARS_INTERFACE 271 +#define TARS_IDENTIFIER 272 +#define TARS_OUT 273 +#define TARS_OP 274 +#define TARS_KEY 275 +#define TARS_ROUTE_KEY 276 +#define TARS_REQUIRE 277 +#define TARS_OPTIONAL 278 +#define TARS_CONST_INTEGER 279 +#define TARS_CONST_FLOAT 280 +#define TARS_FALSE 281 +#define TARS_TRUE 282 +#define TARS_STRING_LITERAL 283 +#define TARS_SCOPE_DELIMITER 284 +#define TARS_CONST 285 +#define TARS_ENUM 286 +#define TARS_UNSIGNED 287 +#define BAD_CHAR 288 /* Copy the first part of user declarations. */ -#line 17 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:339 */ +#line 17 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" #include #include @@ -76,15 +150,11 @@ using namespace std; #define YYDEBUG 1 #define YYINITDEPTH 10000 -#line 80 "tars.tab.cpp" /* yacc.c:339 */ -# ifndef YY_NULLPTR -# if defined __cplusplus && 201103L <= __cplusplus -# define YY_NULLPTR nullptr -# else -# define YY_NULLPTR 0 -# endif -# endif +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE @@ -94,74 +164,25 @@ using namespace std; # define YYERROR_VERBOSE 0 #endif -/* In a future release of Bison, this section will be replaced - by #include "tars.tab.hpp". */ -#ifndef YY_YY_TARS_TAB_HPP_INCLUDED -# define YY_YY_TARS_TAB_HPP_INCLUDED -/* Debug traces. */ -#ifndef YYDEBUG -# define YYDEBUG 1 -#endif -#if YYDEBUG -extern int yydebug; +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 #endif -/* Token type. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - enum yytokentype - { - TARS_VOID = 258, - TARS_STRUCT = 259, - TARS_BOOL = 260, - TARS_BYTE = 261, - TARS_SHORT = 262, - TARS_INT = 263, - TARS_DOUBLE = 264, - TARS_FLOAT = 265, - TARS_LONG = 266, - TARS_STRING = 267, - TARS_VECTOR = 268, - TARS_MAP = 269, - TARS_NAMESPACE = 270, - TARS_INTERFACE = 271, - TARS_IDENTIFIER = 272, - TARS_OUT = 273, - TARS_OP = 274, - TARS_KEY = 275, - TARS_ROUTE_KEY = 276, - TARS_REQUIRE = 277, - TARS_OPTIONAL = 278, - TARS_CONST_INTEGER = 279, - TARS_CONST_FLOAT = 280, - TARS_FALSE = 281, - TARS_TRUE = 282, - TARS_STRING_LITERAL = 283, - TARS_SCOPE_DELIMITER = 284, - TARS_CONST = 285, - TARS_ENUM = 286, - TARS_UNSIGNED = 287, - BAD_CHAR = 288 - }; -#endif - -/* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 #endif -extern YYSTYPE yylval; - -int yyparse (void); - -#endif /* !YY_YY_TARS_TAB_HPP_INCLUDED */ /* Copy the second part of user declarations. */ -#line 165 "tars.tab.cpp" /* yacc.c:358 */ + +/* Line 216 of yacc.c. */ +#line 186 "tars.tab.cpp" #ifdef short # undef short @@ -175,8 +196,11 @@ typedef unsigned char yytype_uint8; #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; -#else +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) typedef signed char yytype_int8; +#else +typedef short int yytype_int8; #endif #ifdef YYTYPE_UINT16 @@ -196,7 +220,8 @@ typedef short int yytype_int16; # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t -# elif ! defined YYSIZE_T +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else @@ -210,68 +235,39 @@ typedef short int yytype_int16; # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ -# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ -# define YY_(Msgid) Msgid -# endif -#endif - -#ifndef YY_ATTRIBUTE -# if (defined __GNUC__ \ - && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ - || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C -# define YY_ATTRIBUTE(Spec) __attribute__(Spec) -# else -# define YY_ATTRIBUTE(Spec) /* empty */ -# endif -#endif - -#ifndef YY_ATTRIBUTE_PURE -# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) -#endif - -#ifndef YY_ATTRIBUTE_UNUSED -# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) -#endif - -#if !defined _Noreturn \ - && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) -# if defined _MSC_VER && 1200 <= _MSC_VER -# define _Noreturn __declspec (noreturn) -# else -# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) +# define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) +# define YYUSE(e) ((void) (e)) #else -# define YYUSE(E) /* empty */ +# define YYUSE(e) /* empty */ #endif -#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ -/* Suppress an incorrect diagnostic about yylval being uninitialized. */ -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ - _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") -# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ - _Pragma ("GCC diagnostic pop") +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) #else -# define YY_INITIAL_VALUE(Value) Value -#endif -#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int i) +#else +static int +YYID (i) + int i; #endif -#ifndef YY_INITIAL_VALUE -# define YY_INITIAL_VALUE(Value) /* Nothing. */ +{ + return i; +} #endif - #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -289,11 +285,11 @@ typedef short int yytype_int16; # define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ - /* Use EXIT_SUCCESS as a witness for stdlib.h. */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 +# ifndef _STDLIB_H +# define _STDLIB_H 1 # endif # endif # endif @@ -301,8 +297,8 @@ typedef short int yytype_int16; # endif # ifdef YYSTACK_ALLOC - /* Pacify GCC's 'empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely @@ -316,23 +312,25 @@ typedef short int yytype_int16; # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif -# if (defined __cplusplus && ! defined EXIT_SUCCESS \ +# if (defined __cplusplus && ! defined _STDLIB_H \ && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) + && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 +# ifndef _STDLIB_H +# define _STDLIB_H 1 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if ! defined malloc && ! defined EXIT_SUCCESS +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if ! defined free && ! defined EXIT_SUCCESS +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif @@ -342,14 +340,14 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ - || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { - yytype_int16 yyss_alloc; - YYSTYPE yyvs_alloc; -}; + yytype_int16 yyss; + YYSTYPE yyvs; + }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) @@ -360,46 +358,42 @@ union yyalloc ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) -# define YYCOPY_NEEDED 1 +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (0) +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) #endif -#if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from SRC to DST. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(Dst, Src, Count) \ - __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) -# else -# define YYCOPY(Dst, Src, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (Dst)[yyi] = (Src)[yyi]; \ - } \ - while (0) -# endif -# endif -#endif /* !YYCOPY_NEEDED */ - /* YYFINAL -- State number of the termination state. */ #define YYFINAL 75 /* YYLAST -- Last index in YYTABLE. */ @@ -411,19 +405,17 @@ union yyalloc #define YYNNTS 42 /* YYNRULES -- Number of rules. */ #define YYNRULES 137 -/* YYNSTATES -- Number of states. */ +/* YYNRULES -- Number of states. */ #define YYNSTATES 199 -/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned - by yylex, with out-of-bounds checking. */ +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 288 -#define YYTRANSLATE(YYX) \ +#define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) -/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, without out-of-bounds checking. */ +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -458,7 +450,71 @@ static const yytype_uint8 yytranslate[] = }; #if YYDEBUG - /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint16 yyprhs[] = +{ + 0, 0, 3, 5, 6, 11, 12, 17, 19, 20, + 22, 24, 26, 28, 30, 32, 33, 39, 42, 45, + 49, 51, 53, 55, 59, 60, 61, 68, 69, 77, + 79, 83, 84, 90, 93, 96, 100, 104, 106, 107, + 109, 113, 116, 118, 120, 121, 123, 127, 130, 135, + 138, 143, 145, 147, 149, 151, 152, 158, 161, 164, + 167, 171, 173, 174, 176, 180, 186, 192, 196, 199, + 202, 205, 207, 209, 211, 213, 215, 217, 219, 223, + 228, 231, 237, 241, 246, 249, 251, 253, 257, 259, + 263, 265, 267, 270, 272, 275, 277, 280, 282, 284, + 286, 288, 290, 292, 294, 299, 303, 308, 311, 318, + 322, 324, 327, 331, 333, 335, 337, 339, 341, 343, + 345, 347, 349, 351, 353, 355, 357, 359, 361, 363, + 365, 367, 369, 371, 373, 375, 377, 379 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 47, 0, -1, 48, -1, -1, 51, 49, 34, 48, + -1, -1, 1, 34, 50, 48, -1, 51, -1, -1, + 57, -1, 62, -1, 73, -1, 59, -1, 52, -1, + 80, -1, -1, 54, 53, 35, 55, 36, -1, 31, + 17, -1, 31, 87, -1, 56, 37, 55, -1, 56, + -1, 17, -1, 87, -1, 17, 38, 79, -1, -1, + -1, 15, 17, 58, 35, 48, 36, -1, -1, 20, + 39, 86, 37, 60, 61, 40, -1, 17, -1, 61, + 37, 17, -1, -1, 64, 63, 35, 65, 36, -1, + 16, 17, -1, 16, 87, -1, 66, 34, 65, -1, + 1, 34, 65, -1, 66, -1, -1, 67, -1, 68, + 70, 41, -1, 69, 19, -1, 82, -1, 3, -1, + -1, 81, -1, 70, 37, 81, -1, 72, 81, -1, + 70, 37, 72, 81, -1, 71, 81, -1, 70, 37, + 71, 81, -1, 72, -1, 71, -1, 21, -1, 18, + -1, -1, 75, 74, 35, 76, 36, -1, 4, 17, + -1, 4, 87, -1, 4, 1, -1, 77, 34, 76, + -1, 77, -1, -1, 78, -1, 24, 22, 81, -1, + 24, 22, 81, 38, 79, -1, 24, 23, 81, 38, + 79, -1, 24, 23, 81, -1, 22, 81, -1, 23, + 81, -1, 24, 81, -1, 81, -1, 24, -1, 25, + -1, 28, -1, 26, -1, 27, -1, 17, -1, 86, + 29, 17, -1, 30, 81, 38, 79, -1, 82, 17, + -1, 82, 17, 39, 24, 40, -1, 82, 42, 17, + -1, 82, 17, 43, 24, -1, 82, 87, -1, 82, + -1, 1, -1, 83, 43, 24, -1, 83, -1, 83, + 43, 1, -1, 5, -1, 6, -1, 32, 6, -1, + 7, -1, 32, 7, -1, 8, -1, 32, 8, -1, + 11, -1, 10, -1, 9, -1, 12, -1, 84, -1, + 85, -1, 86, -1, 13, 44, 82, 45, -1, 13, + 44, 1, -1, 13, 44, 82, 1, -1, 13, 1, + -1, 14, 44, 82, 37, 82, 45, -1, 14, 44, + 1, -1, 17, -1, 29, 17, -1, 86, 29, 17, + -1, 4, -1, 3, -1, 5, -1, 6, -1, 7, + -1, 8, -1, 10, -1, 9, -1, 12, -1, 13, + -1, 20, -1, 14, -1, 15, -1, 16, -1, 18, + -1, 22, -1, 23, -1, 24, -1, 25, -1, 26, + -1, 27, -1, 28, -1, 30, -1, 31, -1, 32, + -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { 0, 68, 68, 75, 74, 79, 78, 83, 88, 95, @@ -478,7 +534,7 @@ static const yytype_uint16 yyrline[] = }; #endif -#if YYDEBUG || YYERROR_VERBOSE || 0 +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = @@ -491,21 +547,21 @@ static const char *const yytname[] = "TARS_CONST_FLOAT", "TARS_FALSE", "TARS_TRUE", "TARS_STRING_LITERAL", "TARS_SCOPE_DELIMITER", "TARS_CONST", "TARS_ENUM", "TARS_UNSIGNED", "BAD_CHAR", "';'", "'{'", "'}'", "','", "'='", "'['", "']'", "')'", - "'*'", "':'", "'<'", "'>'", "$accept", "start", "definitions", "$@1", - "$@2", "definition", "enum_def", "@3", "enum_id", "enumerator_list", - "enumerator", "namespace_def", "@4", "key_def", "$@5", "key_members", + "'*'", "':'", "'<'", "'>'", "$accept", "start", "definitions", "@1", + "@2", "definition", "enum_def", "@3", "enum_id", "enumerator_list", + "enumerator", "namespace_def", "@4", "key_def", "@5", "key_members", "interface_def", "@6", "interface_id", "interface_exports", "interface_export", "operation", "operation_preamble", "return_type", "parameters", "routekey_qualifier", "out_qualifier", "struct_def", "@7", "struct_id", "struct_exports", "data_member", "struct_type_id", "const_initializer", "const_def", "type_id", "type", "type_no", "vector", - "map", "scoped_name", "keyword", YY_NULLPTR + "map", "scoped_name", "keyword", 0 }; #endif # ifdef YYPRINT -/* YYTOKNUM[NUM] -- (External) token number corresponding to the - (internal) symbol number NUM (which must be that of a token). */ +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, @@ -516,45 +572,47 @@ static const yytype_uint16 yytoknum[] = }; # endif -#define YYPACT_NINF -146 - -#define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-146))) - -#define YYTABLE_NINF -113 - -#define yytable_value_is_error(Yytable_value) \ - 0 +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 46, 47, 49, 48, 50, 48, 48, 48, 51, + 51, 51, 51, 51, 51, 53, 52, 54, 54, 55, + 55, 56, 56, 56, 56, 58, 57, 60, 59, 61, + 61, 63, 62, 64, 64, 65, 65, 65, 65, 66, + 67, 68, 69, 69, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 71, 72, 74, 73, 75, 75, 75, + 76, 76, 76, 77, 78, 78, 78, 78, 78, 78, + 78, 78, 79, 79, 79, 79, 79, 79, 79, 80, + 81, 81, 81, 81, 81, 81, 81, 82, 82, 82, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 84, 84, 84, 84, 85, 85, + 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87 +}; - /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -static const yytype_int16 yypact[] = +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = { - 145, -22, 286, 20, 445, 16, 372, 475, 42, -146, - 26, -146, -146, -146, -146, -146, -146, -146, -146, -146, - -146, -146, -146, -146, -146, -146, -146, -146, -146, -146, - -146, -146, -146, -146, -146, -146, -146, -146, -146, -146, - -146, -146, -146, -146, -146, -146, -146, -146, -146, -146, - -146, -146, 11, -146, -146, -146, -146, -146, -146, -146, - -146, -146, 7, 2, -146, 37, 51, 23, 182, 19, - -146, -146, 35, -146, -146, -146, 31, 32, 33, 49, - 102, 66, -2, -146, 386, 415, -146, -146, -146, -146, - 153, -5, 69, -146, 8, 87, 102, 505, 252, 220, - -146, 120, -146, -146, 5, -146, 29, 78, -146, -146, - -146, -146, -146, -146, 79, 86, 88, -146, -146, -146, - -146, -146, 75, 80, 83, -146, 81, -146, 90, 93, - -146, 12, 112, -146, 372, 372, 314, 98, 103, -146, - -146, 107, 122, -146, -146, 533, 127, 108, -146, 153, - -146, 505, 252, -146, 252, -146, -146, 15, 68, 82, - -146, -146, -146, -146, 372, 372, -146, -146, 220, -146, - -146, -26, 109, 118, -146, -146, -146, -146, -146, 343, - -146, -146, -146, 117, 119, -146, 146, -146, -146, 372, - 372, -146, 153, 153, -146, -146, -146, -146, -146 + 0, 2, 1, 0, 4, 0, 4, 1, 0, 1, + 1, 1, 1, 1, 1, 0, 5, 2, 2, 3, + 1, 1, 1, 3, 0, 0, 6, 0, 7, 1, + 3, 0, 5, 2, 2, 3, 3, 1, 0, 1, + 3, 2, 1, 1, 0, 1, 3, 2, 4, 2, + 4, 1, 1, 1, 1, 0, 5, 2, 2, 2, + 3, 1, 0, 1, 3, 5, 5, 3, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 1, 3, 4, + 2, 5, 3, 4, 2, 1, 1, 3, 1, 3, + 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 4, 3, 4, 2, 6, 3, + 1, 2, 3, 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 }; - /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE does not specify something else to do. Zero - means the default is an error. */ +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ static const yytype_uint8 yydefact[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, @@ -579,17 +637,7 @@ static const yytype_uint8 yydefact[] = 0, 46, 0, 0, 30, 50, 48, 65, 66 }; - /* YYPGOTO[NTERM-NUM]. */ -static const yytype_int16 yypgoto[] = -{ - -146, -146, -65, -146, -146, -146, -146, -146, -146, 13, - -146, -146, -146, -146, -146, -146, -146, -146, -146, -109, - -146, -146, -146, -146, -146, -17, -13, -146, -146, -146, - -1, -146, -146, -145, -146, -6, -82, -146, -146, -146, - -51, 3 -}; - - /* YYDEFGOTO[NTERM-NUM]. */ +/* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { -1, 8, 9, 76, 80, 10, 11, 77, 12, 123, @@ -599,9 +647,48 @@ static const yytype_int16 yydefgoto[] = 72, 125 }; - /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule whose - number is the opposite. If YYTABLE_NINF, syntax error. */ +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -146 +static const yytype_int16 yypact[] = +{ + 145, -22, 286, 20, 445, 16, 372, 475, 42, -146, + 26, -146, -146, -146, -146, -146, -146, -146, -146, -146, + -146, -146, -146, -146, -146, -146, -146, -146, -146, -146, + -146, -146, -146, -146, -146, -146, -146, -146, -146, -146, + -146, -146, -146, -146, -146, -146, -146, -146, -146, -146, + -146, -146, 11, -146, -146, -146, -146, -146, -146, -146, + -146, -146, 7, 2, -146, 37, 51, 23, 182, 19, + -146, -146, 35, -146, -146, -146, 31, 32, 33, 49, + 102, 66, -2, -146, 386, 415, -146, -146, -146, -146, + 153, -5, 69, -146, 8, 87, 102, 505, 252, 220, + -146, 120, -146, -146, 5, -146, 29, 78, -146, -146, + -146, -146, -146, -146, 79, 86, 88, -146, -146, -146, + -146, -146, 75, 80, 83, -146, 81, -146, 90, 93, + -146, 12, 112, -146, 372, 372, 314, 98, 103, -146, + -146, 107, 122, -146, -146, 533, 127, 108, -146, 153, + -146, 505, 252, -146, 252, -146, -146, 15, 68, 82, + -146, -146, -146, -146, 372, 372, -146, -146, 220, -146, + -146, -26, 109, 118, -146, -146, -146, -146, -146, 343, + -146, -146, -146, 117, 119, -146, 146, -146, -146, 372, + 372, -146, 153, 153, -146, -146, -146, -146, -146 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = +{ + -146, -146, -65, -146, -146, -146, -146, -146, -146, 13, + -146, -146, -146, -146, -146, -146, -146, -146, -146, -109, + -146, -146, -146, -146, -146, -17, -13, -146, -146, -146, + -1, -146, -146, -145, -146, -6, -82, -146, -146, -146, + -51, 3 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -113 static const yytype_int16 yytable[] = { 67, 82, 104, 106, 175, 48, 143, 51, 83, 118, @@ -724,8 +811,8 @@ static const yytype_int16 yycheck[] = -1, -1, 29, -1, -1, 32 }; - /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 1, 4, 15, 16, 20, 30, 31, 47, 48, @@ -750,80 +837,96 @@ static const yytype_uint8 yystos[] = 72, 81, 38, 38, 17, 81, 81, 79, 79 }; - /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint8 yyr1[] = -{ - 0, 46, 47, 49, 48, 50, 48, 48, 48, 51, - 51, 51, 51, 51, 51, 53, 52, 54, 54, 55, - 55, 56, 56, 56, 56, 58, 57, 60, 59, 61, - 61, 63, 62, 64, 64, 65, 65, 65, 65, 66, - 67, 68, 69, 69, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 71, 72, 74, 73, 75, 75, 75, - 76, 76, 76, 77, 78, 78, 78, 78, 78, 78, - 78, 78, 79, 79, 79, 79, 79, 79, 79, 80, - 81, 81, 81, 81, 81, 81, 81, 82, 82, 82, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 84, 84, 84, 84, 85, 85, - 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87 -}; - - /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = -{ - 0, 2, 1, 0, 4, 0, 4, 1, 0, 1, - 1, 1, 1, 1, 1, 0, 5, 2, 2, 3, - 1, 1, 1, 3, 0, 0, 6, 0, 7, 1, - 3, 0, 5, 2, 2, 3, 3, 1, 0, 1, - 3, 2, 1, 1, 0, 1, 3, 2, 4, 2, - 4, 1, 1, 1, 1, 0, 5, 2, 2, 2, - 3, 1, 0, 1, 3, 5, 5, 3, 2, 2, - 2, 1, 1, 1, 1, 1, 1, 1, 3, 4, - 2, 5, 3, 4, 2, 1, 1, 3, 1, 3, - 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, - 1, 1, 1, 1, 4, 3, 4, 2, 6, 3, - 1, 2, 3, 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 -}; +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ yyerror (YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (0) + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + -/* Error token number */ -#define YYTERROR 1 -#define YYERRCODE 256 +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ +#ifndef YY_LOCATION_PRINT +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + /* Enable debugging if requested. */ #if YYDEBUG @@ -832,46 +935,54 @@ while (0) # define YYFPRINTF fprintf # endif -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (0) - -/* This macro is provided for backward compatibility. */ -#ifndef YY_LOCATION_PRINT -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -#endif +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Type, Value); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (0) +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ -/*----------------------------------------. -| Print this symbol's value on YYOUTPUT. | -`----------------------------------------*/ - +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif { - FILE *yyo = yyoutput; - YYUSE (yyo); if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); # endif - YYUSE (yytype); + switch (yytype) + { + default: + break; + } } @@ -879,11 +990,22 @@ yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvalue | Print this symbol on YYOUTPUT. | `--------------------------------*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif { - YYFPRINTF (yyoutput, "%s %s (", - yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); yy_symbol_value_print (yyoutput, yytype, yyvaluep); YYFPRINTF (yyoutput, ")"); @@ -894,54 +1016,66 @@ yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) | TOP (included). | `------------------------------------------------------------------*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) +#else static void -yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +yy_stack_print (bottom, top) + yytype_int16 *bottom; + yytype_int16 *top; +#endif { YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } + for (; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); YYFPRINTF (stderr, "\n"); } -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (0) +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule) +#else static void -yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule) +yy_reduce_print (yyvsp, yyrule) + YYSTYPE *yyvsp; + int yyrule; +#endif { - unsigned long int yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; + unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", - yyrule - 1, yylno); + yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { - YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, - yystos[yyssp[yyi + 1 - yynrhs]], - &(yyvsp[(yyi + 1) - (yynrhs)]) - ); - YYFPRINTF (stderr, "\n"); + fprintf (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + fprintf (stderr, "\n"); } } -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyssp, yyvsp, Rule); \ -} while (0) +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule); \ +} while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ @@ -955,7 +1089,7 @@ int yydebug; /* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH +#ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif @@ -970,6 +1104,7 @@ int yydebug; # define YYMAXDEPTH 10000 #endif + #if YYERROR_VERBOSE @@ -978,8 +1113,15 @@ int yydebug; # define yystrlen strlen # else /* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) @@ -995,8 +1137,16 @@ yystrlen (const char *yystr) # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif { char *yyd = yydest; const char *yys = yysrc; @@ -1026,27 +1176,27 @@ yytnamerr (char *yyres, const char *yystr) char const *yyp = yystr; for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - /* Fall through. */ - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; - - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } do_not_strip_quotes: ; } @@ -1057,209 +1207,211 @@ yytnamerr (char *yyres, const char *yystr) } # endif -/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message - about the unexpected token YYTOKEN for the state stack whose top is - YYSSP. - - Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is - not large enough to hold the message. In that case, also set - *YYMSG_ALLOC to the required number of bytes. Return 2 if the - required number of bytes is too large to store. */ -static int -yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, - yytype_int16 *yyssp, int yytoken) +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) { - YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); - YYSIZE_T yysize = yysize0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - /* Internationalized format string. */ - const char *yyformat = YY_NULLPTR; - /* Arguments of yyformat. */ - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - /* Number of reported tokens (one for the "unexpected", one per - "expected"). */ - int yycount = 0; - - /* There are many possibilities here to consider: - - If this state is a consistent state with a default action, then - the only way this function was invoked is if the default action - is an error action. In that case, don't check for expected - tokens because there are none. - - The only way there can be no lookahead present (in yychar) is if - this state is a consistent state with a default action. Thus, - detecting the absence of a lookahead is sufficient to determine - that there is no unexpected or expected token to report. In that - case, just report a simple "syntax error". - - Don't assume there isn't a lookahead just because this state is a - consistent state with a default action. There might have been a - previous inconsistent state, consistent state with a non-default - action, or user semantic action that manipulated yychar. - - Of course, the expected token list depends on states to have - correct lookahead information, and it depends on the parser not - to perform extra reductions after fetching a lookahead from the - scanner and before detecting a syntax error. Thus, state merging - (from LALR or IELR) and default reductions corrupt the expected - token list. However, the list is correct for canonical LR with - one exception: it will still contain any token that will not be - accepted due to an error action in a later state. - */ - if (yytoken != YYEMPTY) - { - int yyn = yypact[*yyssp]; - yyarg[yycount++] = yytname[yytoken]; - if (!yypact_value_is_default (yyn)) - { - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. In other words, skip the first -YYN actions for - this state because they are default actions. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yyx; - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR - && !yytable_value_is_error (yytable[yyx + yyn])) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - break; - } - yyarg[yycount++] = yytname[yyx]; - { - YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } - } - } - } + int yyn = yypact[yystate]; - switch (yycount) - { -# define YYCASE_(N, S) \ - case N: \ - yyformat = S; \ - break - YYCASE_(0, YY_("syntax error")); - YYCASE_(1, YY_("syntax error, unexpected %s")); - YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); - YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); - YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); - YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); -# undef YYCASE_ - } - - { - YYSIZE_T yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } - - if (*yymsg_alloc < yysize) + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else { - *yymsg_alloc = 2 * yysize; - if (! (yysize <= *yymsg_alloc - && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) - *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; - return 1; + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; } - - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - { - char *yyp = *yymsg; - int yyi = 0; - while ((*yyp = *yyformat) != '\0') - if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyformat += 2; - } - else - { - yyp++; - yyformat++; - } - } - return 0; } #endif /* YYERROR_VERBOSE */ + /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif { YYUSE (yyvaluep); + if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yytype); - YY_IGNORE_MAYBE_UNINITIALIZED_END + switch (yytype) + { + + default: + break; + } } + +/* Prevent warnings from -Wmissing-prototypes. */ +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ -/* The lookahead symbol. */ + +/* The look-ahead symbol. */ int yychar; -/* The semantic value of the lookahead symbol. */ +/* The semantic value of the look-ahead symbol. */ YYSTYPE yylval; + /* Number of syntax errors so far. */ int yynerrs; + /*----------. | yyparse. | `----------*/ +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) int yyparse (void) -{ - int yystate; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - - /* The stacks and their tools: - 'yyss': related to states. - 'yyvs': related to semantic values. - - Refer to the stacks through separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss; - yytype_int16 *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp; - - YYSIZE_T yystacksize; +#else +int +yyparse () +#endif +#endif +{ + + int yystate; int yyn; int yyresult; - /* Lookahead token as an internal (translated) token number. */ + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ int yytoken = 0; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; @@ -1267,22 +1419,54 @@ yyparse (void) YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp; + + + #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; - yyssp = yyss = yyssa; - yyvsp = yyvs = yyvsa; - yystacksize = YYINITDEPTH; - YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + goto yysetstate; /*------------------------------------------------------------. @@ -1303,23 +1487,25 @@ yyparse (void) #ifdef yyoverflow { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yystacksize); - - yyss = yyss1; - yyvs = yyvs1; + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE @@ -1327,22 +1513,23 @@ yyparse (void) # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; + goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; + yystacksize = YYMAXDEPTH; { - yytype_int16 *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + # undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ @@ -1350,18 +1537,16 @@ yyparse (void) yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; + YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); + (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) - YYABORT; + YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - if (yystate == YYFINAL) - YYACCEPT; - goto yybackup; /*-----------. @@ -1370,20 +1555,20 @@ yyparse (void) yybackup: /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ + look-ahead token if we need one and don't already have one. */ - /* First try to decide what to do without reference to lookahead token. */ + /* First try to decide what to do without reference to look-ahead token. */ yyn = yypact[yystate]; - if (yypact_value_is_default (yyn)) + if (yyn == YYPACT_NINF) goto yydefault; - /* Not known => get a lookahead token if don't already have one. */ + /* Not known => get a look-ahead token if don't already have one. */ - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); - yychar = yylex (); + yychar = YYLEX; } if (yychar <= YYEOF) @@ -1405,27 +1590,29 @@ yybackup: yyn = yytable[yyn]; if (yyn <= 0) { - if (yytable_value_is_error (yyn)) - goto yyerrlab; + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; yyn = -yyn; goto yyreduce; } + if (yyn == YYFINAL) + YYACCEPT; + /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; - /* Shift the lookahead token. */ + /* Shift the look-ahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - /* Discard the shifted token. */ - yychar = YYEMPTY; + /* Discard the shifted token unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; yystate = yyn; - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END goto yynewstate; @@ -1448,7 +1635,7 @@ yyreduce: yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: - '$$ = $1'. + `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison @@ -1462,202 +1649,182 @@ yyreduce: switch (yyn) { case 3: -#line 75 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 75 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 1469 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 5: -#line 79 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 79 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { yyerrok; -} -#line 1477 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 7: -#line 84 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 84 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { g_parse->error("`;' missing after definition"); -} -#line 1485 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 8: -#line 88 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 88 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 1492 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 9: -#line 96 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 96 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - assert((yyvsp[0]) == 0 || NamespacePtr::dynamicCast((yyvsp[0]))); -} -#line 1500 "tars.tab.cpp" /* yacc.c:1646 */ + assert((yyvsp[(1) - (1)]) == 0 || NamespacePtr::dynamicCast((yyvsp[(1) - (1)]))); +;} break; case 10: -#line 100 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 100 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - assert((yyvsp[0]) == 0 || InterfacePtr::dynamicCast((yyvsp[0]))); -} -#line 1508 "tars.tab.cpp" /* yacc.c:1646 */ + assert((yyvsp[(1) - (1)]) == 0 || InterfacePtr::dynamicCast((yyvsp[(1) - (1)]))); +;} break; case 11: -#line 104 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 104 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - assert((yyvsp[0]) == 0 || StructPtr::dynamicCast((yyvsp[0]))); -} -#line 1516 "tars.tab.cpp" /* yacc.c:1646 */ + assert((yyvsp[(1) - (1)]) == 0 || StructPtr::dynamicCast((yyvsp[(1) - (1)]))); +;} break; case 12: -#line 108 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 108 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 1523 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 13: -#line 111 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 111 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - assert((yyvsp[0]) == 0 || EnumPtr::dynamicCast((yyvsp[0]))); -} -#line 1531 "tars.tab.cpp" /* yacc.c:1646 */ + assert((yyvsp[(1) - (1)]) == 0 || EnumPtr::dynamicCast((yyvsp[(1) - (1)]))); +;} break; case 14: -#line 115 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 115 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - assert((yyvsp[0]) == 0 || ConstPtr::dynamicCast((yyvsp[0]))); -} -#line 1539 "tars.tab.cpp" /* yacc.c:1646 */ + assert((yyvsp[(1) - (1)]) == 0 || ConstPtr::dynamicCast((yyvsp[(1) - (1)]))); +;} break; case 15: -#line 124 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 124 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - (yyval) = (yyvsp[0]); -} -#line 1547 "tars.tab.cpp" /* yacc.c:1646 */ + (yyval) = (yyvsp[(1) - (1)]); +;} break; case 16: -#line 128 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 128 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - if((yyvsp[-2])) + if((yyvsp[(3) - (5)])) { g_parse->popContainer(); - (yyval) = (yyvsp[-2]); + (yyval) = (yyvsp[(3) - (5)]); } else { (yyval) = 0; } - (yyval) = (yyvsp[-3]); -} -#line 1565 "tars.tab.cpp" /* yacc.c:1646 */ + (yyval) = (yyvsp[(2) - (5)]); +;} break; case 17: -#line 147 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 147 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { NamespacePtr c = NamespacePtr::dynamicCast(g_parse->currentContainer()); if(!c) { g_parse->error("enum must define in namespace"); } - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (2)])); EnumPtr e = c->createEnum(ident->v); g_parse->pushContainer(e); (yyval) = e; -} -#line 1582 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 18: -#line 160 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 160 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (2)])); g_parse->error("keyword `" + ident->v + "' cannot be used as enumeration name"); - (yyval) = (yyvsp[0]); -} -#line 1592 "tars.tab.cpp" /* yacc.c:1646 */ + (yyval) = (yyvsp[(2) - (2)]); +;} break; case 19: -#line 171 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 171 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - (yyval) = (yyvsp[-1]); -} -#line 1600 "tars.tab.cpp" /* yacc.c:1646 */ + (yyval) = (yyvsp[(2) - (3)]); +;} break; case 20: -#line 175 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 175 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 1607 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 21: -#line 183 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 183 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { TypePtr type = TypePtr::dynamicCast(g_parse->createBuiltin(Builtin::KindLong)); - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); TypeIdPtr tPtr = new TypeId(type, ident->v); tPtr->disableDefault(); EnumPtr e = EnumPtr::dynamicCast(g_parse->currentContainer()); assert(e); e->addMember(tPtr); (yyval) = e; -} -#line 1622 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 22: -#line 194 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 194 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); g_parse->error("keyword `" + ident->v + "' cannot be used as enumerator"); -} -#line 1631 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 23: -#line 199 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 199 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { TypePtr type = TypePtr::dynamicCast(g_parse->createBuiltin(Builtin::KindLong)); - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[-2])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (3)])); TypeIdPtr tPtr = new TypeId(type, ident->v); - ConstGrammarPtr sPtr = ConstGrammarPtr::dynamicCast((yyvsp[0])); + ConstGrammarPtr sPtr = ConstGrammarPtr::dynamicCast((yyvsp[(3) - (3)])); g_parse->checkConstValue(tPtr, sPtr->t); tPtr->setDefault(sPtr->v); EnumPtr e = EnumPtr::dynamicCast(g_parse->currentContainer()); assert(e); e->addMember(tPtr); (yyval) = e; -} -#line 1648 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 24: -#line 212 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 212 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 1655 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 25: -#line 220 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 220 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (2)])); ContainerPtr c = g_parse->currentContainer(); NamespacePtr n = c->createNamespace(ident->v); if(n) @@ -1669,30 +1836,28 @@ yyreduce: { (yyval) = 0; } -} -#line 1674 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 26: -#line 235 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 235 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - if((yyvsp[-3])) + if((yyvsp[(3) - (6)])) { g_parse->popContainer(); - (yyval) = (yyvsp[-3]); + (yyval) = (yyvsp[(3) - (6)]); } else { (yyval) = 0; } -} -#line 1690 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 27: -#line 253 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 253 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[-1])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(3) - (4)])); StructPtr sp = StructPtr::dynamicCast(g_parse->findUserType(ident->v)); if(!sp) { @@ -1700,21 +1865,19 @@ yyreduce: } g_parse->setKeyStruct(sp); -} -#line 1705 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 28: -#line 264 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 264 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 1712 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 29: -#line 272 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 272 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); StructPtr np = g_parse->getKeyStruct(); if(np) { @@ -1724,14 +1887,13 @@ yyreduce: { (yyval) = 0; } -} -#line 1729 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 30: -#line 285 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 285 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(3) - (3)])); StructPtr np = g_parse->getKeyStruct(); if(np) { @@ -1741,14 +1903,13 @@ yyreduce: { (yyval) = 0; } -} -#line 1746 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 31: -#line 304 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 304 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); NamespacePtr c = NamespacePtr::dynamicCast(g_parse->currentContainer()); @@ -1762,94 +1923,85 @@ yyreduce: { (yyval) = 0; } -} -#line 1767 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 32: -#line 321 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 321 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - if((yyvsp[-3])) + if((yyvsp[(2) - (5)])) { g_parse->popContainer(); - (yyval) = GrammarBasePtr::dynamicCast((yyvsp[-3])); + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[(2) - (5)])); } else { (yyval) = 0; } -} -#line 1783 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 33: -#line 338 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 338 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - (yyval) = (yyvsp[0]); -} -#line 1791 "tars.tab.cpp" /* yacc.c:1646 */ + (yyval) = (yyvsp[(2) - (2)]); +;} break; case 34: -#line 342 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 342 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (2)])); g_parse->error("keyword `" + ident->v + "' cannot be used as interface name"); - (yyval) = (yyvsp[0]); -} -#line 1801 "tars.tab.cpp" /* yacc.c:1646 */ + (yyval) = (yyvsp[(2) - (2)]); +;} break; case 35: -#line 353 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 353 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 1808 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 36: -#line 356 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 356 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 1815 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 37: -#line 359 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 359 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { g_parse->error("`;' missing after definition"); -} -#line 1823 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 38: -#line 363 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 363 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 1830 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 40: -#line 377 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 377 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - if((yyvsp[-2])) + if((yyvsp[(1) - (3)])) { g_parse->popContainer(); - (yyval) = GrammarBasePtr::dynamicCast((yyvsp[-2])); + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[(1) - (3)])); } else { (yyval) = 0; } -} -#line 1846 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 41: -#line 394 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 394 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - TypePtr returnType = TypePtr::dynamicCast((yyvsp[-1])); - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + TypePtr returnType = TypePtr::dynamicCast((yyvsp[(1) - (2)])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (2)])); string name = ident->v; InterfacePtr cl = InterfacePtr::dynamicCast(g_parse->currentContainer()); if(cl) @@ -1869,29 +2021,26 @@ yyreduce: { (yyval) = 0; } -} -#line 1874 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 43: -#line 424 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 424 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { (yyval) = 0; -} -#line 1882 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 44: -#line 434 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 434 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 1889 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 45: -#line 437 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 437 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[0])); + TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[(1) - (1)])); OperationPtr op = OperationPtr::dynamicCast(g_parse->currentContainer()); assert(op); @@ -1899,14 +2048,13 @@ yyreduce: { op->createParamDecl(tsp, false, false); } -} -#line 1904 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 46: -#line 448 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 448 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[0])); + TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[(3) - (3)])); OperationPtr op = OperationPtr::dynamicCast(g_parse->currentContainer()); assert(op); @@ -1914,15 +2062,14 @@ yyreduce: { op->createParamDecl(tsp, false, false); } -} -#line 1919 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 47: -#line 459 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 459 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - BoolGrammarPtr isOutParam = BoolGrammarPtr::dynamicCast((yyvsp[-1])); - TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[0])); + BoolGrammarPtr isOutParam = BoolGrammarPtr::dynamicCast((yyvsp[(1) - (2)])); + TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[(2) - (2)])); OperationPtr op = OperationPtr::dynamicCast(g_parse->currentContainer()); assert(op); @@ -1930,15 +2077,14 @@ yyreduce: { op->createParamDecl(tsp, isOutParam->v, false); } -} -#line 1935 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 48: -#line 471 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 471 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - BoolGrammarPtr isOutParam = BoolGrammarPtr::dynamicCast((yyvsp[-1])); - TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[0])); + BoolGrammarPtr isOutParam = BoolGrammarPtr::dynamicCast((yyvsp[(3) - (4)])); + TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[(4) - (4)])); OperationPtr op = OperationPtr::dynamicCast(g_parse->currentContainer()); assert(op); @@ -1946,15 +2092,14 @@ yyreduce: { op->createParamDecl(tsp, isOutParam->v, false); } -} -#line 1951 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 49: -#line 483 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 483 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - BoolGrammarPtr isRouteKeyParam = BoolGrammarPtr::dynamicCast((yyvsp[-1])); - TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[0])); + BoolGrammarPtr isRouteKeyParam = BoolGrammarPtr::dynamicCast((yyvsp[(1) - (2)])); + TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[(2) - (2)])); OperationPtr op = OperationPtr::dynamicCast(g_parse->currentContainer()); assert(op); @@ -1962,15 +2107,14 @@ yyreduce: { op->createParamDecl(tsp, false, isRouteKeyParam->v); } -} -#line 1967 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 50: -#line 495 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 495 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - BoolGrammarPtr isRouteKeyParam = BoolGrammarPtr::dynamicCast((yyvsp[-1])); - TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[0])); + BoolGrammarPtr isRouteKeyParam = BoolGrammarPtr::dynamicCast((yyvsp[(3) - (4)])); + TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[(4) - (4)])); OperationPtr op = OperationPtr::dynamicCast(g_parse->currentContainer()); assert(op); @@ -1978,50 +2122,45 @@ yyreduce: { op->createParamDecl(tsp, false, isRouteKeyParam->v); } -} -#line 1983 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 51: -#line 507 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 507 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { g_parse->error("'out' must be defined with a type"); -} -#line 1991 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 52: -#line 511 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 511 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { g_parse->error("'routekey' must be defined with a type"); -} -#line 1999 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 53: -#line 520 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 520 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { BoolGrammarPtr routekey = new BoolGrammar; routekey->v = true; (yyval) = GrammarBasePtr::dynamicCast(routekey); -} -#line 2009 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 54: -#line 531 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 531 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { BoolGrammarPtr out = new BoolGrammar; out->v = true; (yyval) = GrammarBasePtr::dynamicCast(out); -} -#line 2019 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 55: -#line 542 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 542 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); NamespacePtr np = NamespacePtr::dynamicCast(g_parse->currentContainer()); if(np) { @@ -2040,18 +2179,17 @@ yyreduce: { g_parse->error("struct '" + ident->v + "' must definition in namespace"); } -} -#line 2045 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 56: -#line 564 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 564 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - if((yyvsp[-3])) + if((yyvsp[(2) - (5)])) { g_parse->popContainer(); } - (yyval) = (yyvsp[-3]); + (yyval) = (yyvsp[(2) - (5)]); StructPtr st = StructPtr::dynamicCast((yyval)); assert(st); @@ -2059,262 +2197,241 @@ yyreduce: { g_parse->error("struct `" + st->getSid() + "' must have at least one member"); } -} -#line 2064 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 57: -#line 584 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 584 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - (yyval) = (yyvsp[0]); -} -#line 2072 "tars.tab.cpp" /* yacc.c:1646 */ + (yyval) = (yyvsp[(2) - (2)]); +;} break; case 58: -#line 588 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 588 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (2)])); g_parse->error("keyword `" + ident->v + "' cannot be used as struct name"); -} -#line 2082 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 59: -#line 594 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 594 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { g_parse->error("abstract declarator '' used as declaration"); -} -#line 2090 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 60: -#line 603 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 603 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2098 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 61: -#line 607 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 607 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { g_parse->error("';' missing after definition"); -} -#line 2106 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 62: -#line 611 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 611 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2113 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 63: -#line 621 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 621 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - (yyval) = GrammarBasePtr::dynamicCast((yyvsp[0])); -} -#line 2121 "tars.tab.cpp" /* yacc.c:1646 */ + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[(1) - (1)])); +;} break; case 64: -#line 630 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 630 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { StructPtr np = StructPtr::dynamicCast(g_parse->currentContainer()); if(np) { - IntergerGrammarPtr iPtr = IntergerGrammarPtr::dynamicCast((yyvsp[-2])); + IntergerGrammarPtr iPtr = IntergerGrammarPtr::dynamicCast((yyvsp[(1) - (3)])); g_parse->checkTag(iPtr->v); - TypeIdPtr tPtr = TypeIdPtr::dynamicCast((yyvsp[0])); + TypeIdPtr tPtr = TypeIdPtr::dynamicCast((yyvsp[(3) - (3)])); tPtr->setRequire(iPtr->v); np->addTypeId(tPtr); - (yyval) = GrammarBasePtr::dynamicCast((yyvsp[0])); + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[(3) - (3)])); } else { (yyval) = 0; } -} -#line 2143 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 65: -#line 648 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 648 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { StructPtr np = StructPtr::dynamicCast(g_parse->currentContainer()); if(np) { - IntergerGrammarPtr iPtr = IntergerGrammarPtr::dynamicCast((yyvsp[-4])); + IntergerGrammarPtr iPtr = IntergerGrammarPtr::dynamicCast((yyvsp[(1) - (5)])); g_parse->checkTag(iPtr->v); - TypeIdPtr tPtr = TypeIdPtr::dynamicCast((yyvsp[-2])); - ConstGrammarPtr sPtr = ConstGrammarPtr::dynamicCast((yyvsp[0])); + TypeIdPtr tPtr = TypeIdPtr::dynamicCast((yyvsp[(3) - (5)])); + ConstGrammarPtr sPtr = ConstGrammarPtr::dynamicCast((yyvsp[(5) - (5)])); g_parse->checkConstValue(tPtr, sPtr->t); tPtr->setRequire(iPtr->v); tPtr->setDefault(sPtr->v); np->addTypeId(tPtr); - (yyval) = GrammarBasePtr::dynamicCast((yyvsp[-2])); + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[(3) - (5)])); } else { (yyval) = 0; } -} -#line 2169 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 66: -#line 670 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 670 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { StructPtr np = StructPtr::dynamicCast(g_parse->currentContainer()); if(np) { - IntergerGrammarPtr iPtr = IntergerGrammarPtr::dynamicCast((yyvsp[-4])); + IntergerGrammarPtr iPtr = IntergerGrammarPtr::dynamicCast((yyvsp[(1) - (5)])); g_parse->checkTag(iPtr->v); - TypeIdPtr tPtr = TypeIdPtr::dynamicCast((yyvsp[-2])); - ConstGrammarPtr sPtr = ConstGrammarPtr::dynamicCast((yyvsp[0])); + TypeIdPtr tPtr = TypeIdPtr::dynamicCast((yyvsp[(3) - (5)])); + ConstGrammarPtr sPtr = ConstGrammarPtr::dynamicCast((yyvsp[(5) - (5)])); g_parse->checkConstValue(tPtr, sPtr->t); tPtr->setOptional(iPtr->v); tPtr->setDefault(sPtr->v); np->addTypeId(tPtr); - (yyval) = GrammarBasePtr::dynamicCast((yyvsp[-2])); + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[(3) - (5)])); } else { (yyval) = 0; } -} -#line 2195 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 67: -#line 692 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 692 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { StructPtr np = StructPtr::dynamicCast(g_parse->currentContainer()); if(np) { - IntergerGrammarPtr iPtr = IntergerGrammarPtr::dynamicCast((yyvsp[-2])); + IntergerGrammarPtr iPtr = IntergerGrammarPtr::dynamicCast((yyvsp[(1) - (3)])); g_parse->checkTag(iPtr->v); - TypeIdPtr tPtr = TypeIdPtr::dynamicCast((yyvsp[0])); + TypeIdPtr tPtr = TypeIdPtr::dynamicCast((yyvsp[(3) - (3)])); tPtr->setOptional(iPtr->v); np->addTypeId(tPtr); - (yyval) = GrammarBasePtr::dynamicCast((yyvsp[0])); + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[(3) - (3)])); } else { (yyval) = 0; } -} -#line 2216 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 68: -#line 709 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 709 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { g_parse->error("struct member need 'tag'"); -} -#line 2224 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 69: -#line 713 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 713 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { g_parse->error("struct member need 'tag'"); -} -#line 2232 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 70: -#line 717 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 717 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { g_parse->error("struct member need 'require' or 'optional'"); -} -#line 2240 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 71: -#line 721 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 721 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { g_parse->error("struct member need 'tag' or 'require' or 'optional'"); -} -#line 2248 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 72: -#line 730 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 730 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - IntergerGrammarPtr intVal = IntergerGrammarPtr::dynamicCast((yyvsp[0])); + IntergerGrammarPtr intVal = IntergerGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); ostringstream sstr; sstr << intVal->v; ConstGrammarPtr c = new ConstGrammar(); c->t = ConstGrammar::VALUE; c->v = sstr.str(); (yyval) = c; -} -#line 2262 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 73: -#line 740 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 740 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - FloatGrammarPtr floatVal = FloatGrammarPtr::dynamicCast((yyvsp[0])); + FloatGrammarPtr floatVal = FloatGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); ostringstream sstr; sstr << floatVal->v; ConstGrammarPtr c = new ConstGrammar(); c->t = ConstGrammar::VALUE; c->v = sstr.str(); (yyval) = c; -} -#line 2276 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 74: -#line 750 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 750 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); ConstGrammarPtr c = new ConstGrammar(); c->t = ConstGrammar::STRING; c->v = ident->v; (yyval) = c; -} -#line 2288 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 75: -#line 758 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 758 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); ConstGrammarPtr c = new ConstGrammar(); c->t = ConstGrammar::BOOL; c->v = ident->v; (yyval) = c; -} -#line 2300 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 76: -#line 766 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 766 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); ConstGrammarPtr c = new ConstGrammar(); c->t = ConstGrammar::BOOL; c->v = ident->v; (yyval) = c; -} -#line 2312 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 77: -#line 774 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 774 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); if (g_parse->checkEnum(ident->v) == false) { @@ -2324,16 +2441,15 @@ yyreduce: c->t = ConstGrammar::ENUM; c->v = ident->v; (yyval) = c; -} -#line 2329 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 78: -#line 787 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 787 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr scoped = StringGrammarPtr::dynamicCast((yyvsp[-2])); - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr scoped = StringGrammarPtr::dynamicCast((yyvsp[(1) - (3)])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(3) - (3)])); if (g_parse->checkEnum(ident->v) == false) { @@ -2343,12 +2459,11 @@ yyreduce: c->t = ConstGrammar::ENUM; c->v = scoped->v + "::" + ident->v; (yyval) = c; -} -#line 2348 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 79: -#line 807 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 807 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { NamespacePtr np = NamespacePtr::dynamicCast(g_parse->currentContainer()); if(!np) @@ -2356,230 +2471,206 @@ yyreduce: g_parse->error("const type must define in namespace"); } - TypeIdPtr t = TypeIdPtr::dynamicCast((yyvsp[-2])); - ConstGrammarPtr c = ConstGrammarPtr::dynamicCast((yyvsp[0])); + TypeIdPtr t = TypeIdPtr::dynamicCast((yyvsp[(2) - (4)])); + ConstGrammarPtr c = ConstGrammarPtr::dynamicCast((yyvsp[(4) - (4)])); ConstPtr cPtr = np->createConst(t, c); (yyval) = cPtr; -} -#line 2365 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 80: -#line 825 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 825 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - TypePtr type = TypePtr::dynamicCast((yyvsp[-1])); - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + TypePtr type = TypePtr::dynamicCast((yyvsp[(1) - (2)])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (2)])); TypeIdPtr typeIdPtr = new TypeId(type, ident->v); (yyval) = GrammarBasePtr::dynamicCast(typeIdPtr); -} -#line 2378 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 81: -#line 834 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 834 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - TypePtr type = g_parse->createVector(TypePtr::dynamicCast((yyvsp[-4]))); - IntergerGrammarPtr iPtrSize = IntergerGrammarPtr::dynamicCast((yyvsp[-1])); + TypePtr type = g_parse->createVector(TypePtr::dynamicCast((yyvsp[(1) - (5)]))); + IntergerGrammarPtr iPtrSize = IntergerGrammarPtr::dynamicCast((yyvsp[(4) - (5)])); g_parse->checkArrayVaid(type,iPtrSize->v); type->setArray(iPtrSize->v); - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[-3])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (5)])); TypeIdPtr typeIdPtr = new TypeId(type, ident->v); (yyval) = GrammarBasePtr::dynamicCast(typeIdPtr); -} -#line 2392 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 82: -#line 844 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 844 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - TypePtr type = g_parse->createVector(TypePtr::dynamicCast((yyvsp[-2]))); + TypePtr type = g_parse->createVector(TypePtr::dynamicCast((yyvsp[(1) - (3)]))); //IntergerGrammarPtr iPtrSize = IntergerGrammarPtr::dynamicCast($4); g_parse->checkPointerVaid(type); type->setPointer(true); - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(3) - (3)])); TypeIdPtr typeIdPtr = new TypeId(type, ident->v); (yyval) = GrammarBasePtr::dynamicCast(typeIdPtr); -} -#line 2406 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 83: -#line 854 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 854 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - TypePtr type = TypePtr::dynamicCast((yyvsp[-3])); - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[-2])); + TypePtr type = TypePtr::dynamicCast((yyvsp[(1) - (4)])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (4)])); TypeIdPtr typeIdPtr = new TypeId(type, ident->v); - IntergerGrammarPtr iPtrSize = IntergerGrammarPtr::dynamicCast((yyvsp[-1])); + IntergerGrammarPtr iPtrSize = IntergerGrammarPtr::dynamicCast((yyvsp[(3) - (4)])); g_parse->checkArrayVaid(type,iPtrSize->v); (yyval) = GrammarBasePtr::dynamicCast(typeIdPtr); -} -#line 2419 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 84: -#line 863 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 863 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (2)])); g_parse->error("keyword `" + ident->v + "' cannot be used as data member name"); -} -#line 2428 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 85: -#line 868 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 868 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { g_parse->error("missing data member name"); -} -#line 2436 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 86: -#line 872 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 872 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { g_parse->error("unkown type"); -} -#line 2444 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 87: -#line 881 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 881 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - TypePtr type = TypePtr::dynamicCast((yyvsp[-2])); - IntergerGrammarPtr iPtrSize = IntergerGrammarPtr::dynamicCast((yyvsp[0])); + TypePtr type = TypePtr::dynamicCast((yyvsp[(1) - (3)])); + IntergerGrammarPtr iPtrSize = IntergerGrammarPtr::dynamicCast((yyvsp[(3) - (3)])); g_parse->checkArrayVaid(type,iPtrSize->v); type->setArray(iPtrSize->v); (yyval) = type; -} -#line 2457 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 88: -#line 890 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 890 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - (yyval) = (yyvsp[0]); -} -#line 2465 "tars.tab.cpp" /* yacc.c:1646 */ + (yyval) = (yyvsp[(1) - (1)]); +;} break; case 89: -#line 894 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 894 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { g_parse->error("array missing size"); -} -#line 2473 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 90: -#line 903 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 903 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { (yyval) = g_parse->createBuiltin(Builtin::KindBool); -} -#line 2481 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 91: -#line 907 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 907 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { (yyval) = g_parse->createBuiltin(Builtin::KindByte); -} -#line 2489 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 92: -#line 911 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 911 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { (yyval) = g_parse->createBuiltin(Builtin::KindShort,true); -} -#line 2497 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 93: -#line 915 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 915 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { (yyval) = g_parse->createBuiltin(Builtin::KindShort); -} -#line 2505 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 94: -#line 919 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 919 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { (yyval) = g_parse->createBuiltin(Builtin::KindInt,true); -} -#line 2513 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 95: -#line 923 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 923 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { (yyval) = g_parse->createBuiltin(Builtin::KindInt); -} -#line 2521 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 96: -#line 927 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 927 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { (yyval) = g_parse->createBuiltin(Builtin::KindLong,true); -} -#line 2529 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 97: -#line 931 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 931 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { (yyval) = g_parse->createBuiltin(Builtin::KindLong); -} -#line 2537 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 98: -#line 935 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 935 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { (yyval) = g_parse->createBuiltin(Builtin::KindFloat); -} -#line 2545 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 99: -#line 939 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 939 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { (yyval) = g_parse->createBuiltin(Builtin::KindDouble); -} -#line 2553 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 100: -#line 943 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 943 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { (yyval) = g_parse->createBuiltin(Builtin::KindString); -} -#line 2561 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 101: -#line 947 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 947 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - (yyval) = GrammarBasePtr::dynamicCast((yyvsp[0])); -} -#line 2569 "tars.tab.cpp" /* yacc.c:1646 */ + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[(1) - (1)])); +;} break; case 102: -#line 951 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 951 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - (yyval) = GrammarBasePtr::dynamicCast((yyvsp[0])); -} -#line 2577 "tars.tab.cpp" /* yacc.c:1646 */ + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[(1) - (1)])); +;} break; case 103: -#line 955 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 955 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(1) - (1)])); TypePtr sp = g_parse->findUserType(ident->v); if(sp) { @@ -2589,277 +2680,232 @@ yyreduce: { g_parse->error("'" + ident->v + "' undefined!"); } -} -#line 2594 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 104: -#line 973 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 973 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - (yyval) = GrammarBasePtr::dynamicCast(g_parse->createVector(TypePtr::dynamicCast((yyvsp[-1])))); -} -#line 2602 "tars.tab.cpp" /* yacc.c:1646 */ + (yyval) = GrammarBasePtr::dynamicCast(g_parse->createVector(TypePtr::dynamicCast((yyvsp[(3) - (4)])))); +;} break; case 105: -#line 977 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 977 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { g_parse->error("vector error"); -} -#line 2610 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 106: -#line 981 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 981 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { g_parse->error("vector missing '>'"); -} -#line 2618 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 107: -#line 985 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 985 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { g_parse->error("vector missing type"); -} -#line 2626 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 108: -#line 994 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 994 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - (yyval) = GrammarBasePtr::dynamicCast(g_parse->createMap(TypePtr::dynamicCast((yyvsp[-3])), TypePtr::dynamicCast((yyvsp[-1])))); -} -#line 2634 "tars.tab.cpp" /* yacc.c:1646 */ + (yyval) = GrammarBasePtr::dynamicCast(g_parse->createMap(TypePtr::dynamicCast((yyvsp[(3) - (6)])), TypePtr::dynamicCast((yyvsp[(5) - (6)])))); +;} break; case 109: -#line 998 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 998 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { g_parse->error("map error"); -} -#line 2642 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 110: -#line 1007 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1007 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2649 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 111: -#line 1010 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1010 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(2) - (2)])); ident->v = "::" + ident->v; (yyval) = GrammarBasePtr::dynamicCast(ident); -} -#line 2659 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 112: -#line 1016 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1016 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { - StringGrammarPtr scoped = StringGrammarPtr::dynamicCast((yyvsp[-2])); - StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StringGrammarPtr scoped = StringGrammarPtr::dynamicCast((yyvsp[(1) - (3)])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[(3) - (3)])); scoped->v += "::"; scoped->v += ident->v; (yyval) = GrammarBasePtr::dynamicCast(scoped); -} -#line 2671 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 113: -#line 1029 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1029 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2678 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 114: -#line 1032 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1032 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2685 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 115: -#line 1035 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1035 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2692 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 116: -#line 1038 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1038 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2699 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 117: -#line 1041 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1041 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2706 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 118: -#line 1044 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1044 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2713 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 119: -#line 1047 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1047 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2720 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 120: -#line 1050 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1050 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2727 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 121: -#line 1053 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1053 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2734 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 122: -#line 1056 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1056 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2741 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 123: -#line 1059 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1059 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2748 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 124: -#line 1062 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1062 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2755 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 125: -#line 1065 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1065 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2762 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 126: -#line 1068 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1068 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2769 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 127: -#line 1071 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1071 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2776 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 128: -#line 1074 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1074 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2783 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 129: -#line 1077 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1077 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2790 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 130: -#line 1080 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1080 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2797 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 131: -#line 1083 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1083 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2804 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 132: -#line 1086 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1086 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2811 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 133: -#line 1089 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1089 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2818 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 134: -#line 1092 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1092 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2825 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 135: -#line 1095 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1095 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2832 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 136: -#line 1098 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1098 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2839 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; case 137: -#line 1101 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1646 */ +#line 1101 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" { -} -#line 2846 "tars.tab.cpp" /* yacc.c:1646 */ +;} break; -#line 2850 "tars.tab.cpp" /* yacc.c:1646 */ +/* Line 1267 of yacc.c. */ +#line 2907 "tars.tab.cpp" default: break; } - /* User semantic actions sometimes alter yychar, and that requires - that yytoken be updated with the new translation. We take the - approach of translating immediately before every use of yytoken. - One alternative is translating here after every semantic action, - but that translation would be missed if the semantic action invokes - YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or - if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an - incorrect destructor might then be invoked immediately. In the - case of YYERROR or YYBACKUP, subsequent parser actions might lead - to an incorrect destructor call or verbose syntax error message - before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); @@ -2868,7 +2914,8 @@ yyreduce: *++yyvsp = yyval; - /* Now 'shift' the result of the reduction. Determine what state + + /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ @@ -2883,14 +2930,10 @@ yyreduce: goto yynewstate; -/*--------------------------------------. -| yyerrlab -- here on detecting error. | -`--------------------------------------*/ +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ yyerrlab: - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); - /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { @@ -2898,36 +2941,37 @@ yyerrlab: #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else -# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ - yyssp, yytoken) { - char const *yymsgp = YY_("syntax error"); - int yysyntax_error_status; - yysyntax_error_status = YYSYNTAX_ERROR; - if (yysyntax_error_status == 0) - yymsgp = yymsg; - else if (yysyntax_error_status == 1) - { - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); - if (!yymsg) - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - yysyntax_error_status = 2; - } - else - { - yysyntax_error_status = YYSYNTAX_ERROR; - yymsgp = yymsg; - } - } - yyerror (yymsgp); - if (yysyntax_error_status == 2) - goto yyexhaustedlab; + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } } -# undef YYSYNTAX_ERROR #endif } @@ -2935,24 +2979,24 @@ yyerrlab: if (yyerrstatus == 3) { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ + /* If just tried and failed to reuse look-ahead token after an + error, discard it. */ if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } else - { - yydestruct ("Error: discarding", - yytoken, &yylval); - yychar = YYEMPTY; - } + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } } - /* Else will try to reuse lookahead token after shifting the error + /* Else will try to reuse look-ahead token after shifting the error token. */ goto yyerrlab1; @@ -2968,7 +3012,7 @@ yyerrorlab: if (/*CONSTCOND*/ 0) goto yyerrorlab; - /* Do not reclaim the symbols of the rule whose action triggered + /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; @@ -2981,37 +3025,38 @@ yyerrorlab: | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ + yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; - if (!yypact_value_is_default (yyn)) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) - YYABORT; + YYABORT; yydestruct ("Error: popping", - yystos[yystate], yyvsp); + yystos[yystate], yyvsp); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + if (yyn == YYFINAL) + YYACCEPT; + *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END /* Shift the error token. */ @@ -3035,7 +3080,7 @@ yyabortlab: yyresult = 1; goto yyreturn; -#if !defined yyoverflow || YYERROR_VERBOSE +#ifndef yyoverflow /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ @@ -3046,22 +3091,17 @@ yyexhaustedlab: #endif yyreturn: - if (yychar != YYEMPTY) - { - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = YYTRANSLATE (yychar); - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); - } - /* Do not reclaim the symbols of the rule whose action triggered + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp); + yystos[*yyssp], yyvsp); YYPOPSTACK (1); } #ifndef yyoverflow @@ -3072,9 +3112,13 @@ yyreturn: if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif - return yyresult; + /* Make sure YYID is used. */ + return YYID (yyresult); } -#line 1105 "/home/tars/TarsCpp/tools/tarsgrammar/tars.y" /* yacc.c:1906 */ + + +#line 1105 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.y" + diff --git a/tools/tarsparse/tars.tab.hpp b/tools/tarsparse/tars.tab.hpp index 547e0174bca35afd7116f1c448ba6aef8bb29f45..49685549dd0e88018b1652e6d51b4aa3bb302b55 100644 --- a/tools/tarsparse/tars.tab.hpp +++ b/tools/tarsparse/tars.tab.hpp @@ -1,13 +1,14 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 2.3. */ -/* Bison interface for Yacc-like parsers in C +/* Skeleton interface for Bison's Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. - This program is free software: you can redistribute it and/or modify + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + the Free Software Foundation; either version 2, or (at your option) + any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -15,7 +16,9 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . */ + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -30,65 +33,87 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ -#ifndef YY_YY_TARS_TAB_HPP_INCLUDED -# define YY_YY_TARS_TAB_HPP_INCLUDED -/* Debug traces. */ -#ifndef YYDEBUG -# define YYDEBUG 1 -#endif -#if YYDEBUG -extern int yydebug; -#endif - -/* Token type. */ +/* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE - enum yytokentype - { - TARS_VOID = 258, - TARS_STRUCT = 259, - TARS_BOOL = 260, - TARS_BYTE = 261, - TARS_SHORT = 262, - TARS_INT = 263, - TARS_DOUBLE = 264, - TARS_FLOAT = 265, - TARS_LONG = 266, - TARS_STRING = 267, - TARS_VECTOR = 268, - TARS_MAP = 269, - TARS_NAMESPACE = 270, - TARS_INTERFACE = 271, - TARS_IDENTIFIER = 272, - TARS_OUT = 273, - TARS_OP = 274, - TARS_KEY = 275, - TARS_ROUTE_KEY = 276, - TARS_REQUIRE = 277, - TARS_OPTIONAL = 278, - TARS_CONST_INTEGER = 279, - TARS_CONST_FLOAT = 280, - TARS_FALSE = 281, - TARS_TRUE = 282, - TARS_STRING_LITERAL = 283, - TARS_SCOPE_DELIMITER = 284, - TARS_CONST = 285, - TARS_ENUM = 286, - TARS_UNSIGNED = 287, - BAD_CHAR = 288 - }; + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + TARS_VOID = 258, + TARS_STRUCT = 259, + TARS_BOOL = 260, + TARS_BYTE = 261, + TARS_SHORT = 262, + TARS_INT = 263, + TARS_DOUBLE = 264, + TARS_FLOAT = 265, + TARS_LONG = 266, + TARS_STRING = 267, + TARS_VECTOR = 268, + TARS_MAP = 269, + TARS_NAMESPACE = 270, + TARS_INTERFACE = 271, + TARS_IDENTIFIER = 272, + TARS_OUT = 273, + TARS_OP = 274, + TARS_KEY = 275, + TARS_ROUTE_KEY = 276, + TARS_REQUIRE = 277, + TARS_OPTIONAL = 278, + TARS_CONST_INTEGER = 279, + TARS_CONST_FLOAT = 280, + TARS_FALSE = 281, + TARS_TRUE = 282, + TARS_STRING_LITERAL = 283, + TARS_SCOPE_DELIMITER = 284, + TARS_CONST = 285, + TARS_ENUM = 286, + TARS_UNSIGNED = 287, + BAD_CHAR = 288 + }; #endif +/* Tokens. */ +#define TARS_VOID 258 +#define TARS_STRUCT 259 +#define TARS_BOOL 260 +#define TARS_BYTE 261 +#define TARS_SHORT 262 +#define TARS_INT 263 +#define TARS_DOUBLE 264 +#define TARS_FLOAT 265 +#define TARS_LONG 266 +#define TARS_STRING 267 +#define TARS_VECTOR 268 +#define TARS_MAP 269 +#define TARS_NAMESPACE 270 +#define TARS_INTERFACE 271 +#define TARS_IDENTIFIER 272 +#define TARS_OUT 273 +#define TARS_OP 274 +#define TARS_KEY 275 +#define TARS_ROUTE_KEY 276 +#define TARS_REQUIRE 277 +#define TARS_OPTIONAL 278 +#define TARS_CONST_INTEGER 279 +#define TARS_CONST_FLOAT 280 +#define TARS_FALSE 281 +#define TARS_TRUE 282 +#define TARS_STRING_LITERAL 283 +#define TARS_SCOPE_DELIMITER 284 +#define TARS_CONST 285 +#define TARS_ENUM 286 +#define TARS_UNSIGNED 287 +#define BAD_CHAR 288 + + + -/* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 #endif - extern YYSTYPE yylval; -int yyparse (void); - -#endif /* !YY_YY_TARS_TAB_HPP_INCLUDED */ diff --git a/util/include/util/tc_autoptr.h b/util/include/util/tc_autoptr.h index 9b2f09c598f3f2fe0364ce50a73b437153a1bcf7..42545cc3de21abb13e687efef27fe9e96f3e0909 100755 --- a/util/include/util/tc_autoptr.h +++ b/util/include/util/tc_autoptr.h @@ -18,7 +18,7 @@ #define __TC_AUTOPTR_H #include "util/tc_ex.h" -// #include "util/tc_atomic.h" +#include "util/tc_platform.h" #include #include @@ -26,6 +26,7 @@ namespace tars { /** +* @brief Null Pointer Exception * @brief 空指针异常 */ struct TC_AutoPtrNull_Exception : public TC_Exception @@ -35,17 +36,20 @@ struct TC_AutoPtrNull_Exception : public TC_Exception }; /** - * @brief 智能指针基类. - * - * 所有需要智能指针支持的类都需要从该对象继承, + * @brief Smart Pointer Base Class + * @brief 智能指针基类 + * + * All classes that require smart pointer support need to inherit from this object. + * 所有需要智能指针支持的类都需要从该对象继承, * */ -class TC_HandleBase +class UTIL_DLL_API TC_HandleBase { public: /** - * @brief 复制. + * @brief Copy + * @brief 复制 * * @return TC_HandleBase& */ @@ -55,12 +59,17 @@ public: } /** + * @brief Increase Count * @brief 增加计数 */ void incRef() { ++_atomic; } /** - * @brief 减少计数, 当计数==0时, 且需要删除数据时, 释放对象 + * @brief Decrease Count/减少计数 + * + * 当计数==0时, 且需要删除数据时, 释放对象 + * When 'count==0' and you need to delete data, you can use this to release object. + * */ void decRef() { @@ -72,15 +81,19 @@ public: } /** + * @brief Get Count * @brief 获取计数. * + * @return int value of count * @return int 计数值 */ int getRef() const { return _atomic; } /** - * @brief 设置不自动释放. + * @brief Set Automatically-Release Off + * @brief 设置不自动释放. * + * @param b Determine whether to be deleted automatically or not, true or false. * @param b 是否自动删除,true or false */ void setNoDelete(bool b) { _bNoDelete = b; } @@ -88,13 +101,15 @@ public: protected: /** - * @brief 构造函数 + * @brief Constructor + * @brief 构造函数 */ TC_HandleBase() : _atomic(0), _bNoDelete(false) { } /** + * @brief Copy Constructor * @brief 拷贝构造 */ TC_HandleBase(const TC_HandleBase&) : _atomic(0), _bNoDelete(false) @@ -102,7 +117,8 @@ protected: } /** - * @brief 析够 + * @brief Destructor + * @brief 析构 */ virtual ~TC_HandleBase() { @@ -111,25 +127,32 @@ protected: protected: /** + * Count * 计数 */ std::atomic _atomic; /** + * Determine whether to be deleted automatically or not * 是否自动删除 */ bool _bNoDelete; }; /** + * @brief Smart Pointer Template Class * @brief 智能指针模板类. * + * This template class an product thread-safe smart pointer which can be placed in a container. + * The smart pointer which is defined by this class can be implemented by reference counting. + * The pointer can be passed in a container. + * + * template T MUST BE inherited from TC_HandleBase + * * 可以放在容器中,且线程安全的智能指针. - * * 通过它定义智能指针,该智能指针通过引用计数实现, - * - * 可以放在容器中传递. - * + * 可以放在容器中传递. + * * template T必须继承于TC_HandleBase */ template @@ -138,11 +161,13 @@ class TC_AutoPtr public: /** + * Element Type * 元素类型 */ typedef T element_type; /** + * @brief Initialize with native pointer, count +1 * @brief 用原生指针初始化, 计数+1. * * @param p @@ -158,6 +183,7 @@ public: } /** + * @brief Initialize with the native pointer of other smart pointer r, count +1. * @brief 用其他智能指针r的原生指针初始化, 计数+1. * * @param Y @@ -175,6 +201,7 @@ public: } /** + * @brief Copy constructor, count +1 * @brief 拷贝构造, 计数+1. * * @param r @@ -190,6 +217,7 @@ public: } /** + * @brief Destructor * @brief 析构 */ ~TC_AutoPtr() @@ -201,6 +229,7 @@ public: } /** + * @brief Assignment, normal pointer * @brief 赋值, 普通指针. * * @param p @@ -227,6 +256,7 @@ public: } /** + * @brief Assignment, other type of smart pointer * @brief 赋值, 其他类型智能指针. * * @param Y @@ -255,6 +285,7 @@ public: } /** + * @brief Assignment, other ruling pointer of this type. * @brief 赋值, 该类型其他执政指针. * * @param r @@ -281,6 +312,7 @@ public: } /** + * @brief Replace other types of smart pointers with current types of smart pointers * @brief 将其他类型的智能指针换成当前类型的智能指针. * * @param Y @@ -294,6 +326,7 @@ public: } /** + * @brief Convert pointers of other native types into smart pointers of the current type * @brief 将其他原生类型的指针转换成当前类型的智能指针. * * @param Y @@ -307,6 +340,7 @@ public: } /** + * @brief Get Native Pointer * @brief 获取原生指针. * * @return T* @@ -317,6 +351,7 @@ public: } /** + * @brief Transfer * @brief 调用. * * @return T* @@ -332,6 +367,7 @@ public: } /** + * @brief Reference * @brief 引用. * * @return T& @@ -347,6 +383,7 @@ public: } /** + * @brief To define whether it is effective or not. * @brief 是否有效. * * @return bool @@ -357,7 +394,8 @@ public: } /** - * @brief 交换指针. + * @brief Swap pointer + * @brief 交换指针. * * @param other */ @@ -369,6 +407,7 @@ public: protected: /** + * @brief Throw Exception * @brief 抛出异常 */ void throwNullHandleException() const; @@ -379,6 +418,7 @@ public: }; /** + * @brief Throw Exception * @brief 抛出异常. * * @param T @@ -392,6 +432,7 @@ TC_AutoPtr::throwNullHandleException() const } /** + * @brief Determine '=='. * @brief ==判断. * * @param T @@ -407,11 +448,13 @@ inline bool operator==(const TC_AutoPtr& lhs, const TC_AutoPtr& rhs) T* l = lhs.get(); U* r = rhs.get(); - // 改为直接比较指针,而不是比较值 + // Compare pointers directly instead of comparing values of the two pointers. + // 改为直接比较指针,而不是比较值 return (l == r); } /** + * @brief Determine '!='. * @brief 不等于判断. * * @param T @@ -427,11 +470,13 @@ inline bool operator!=(const TC_AutoPtr& lhs, const TC_AutoPtr& rhs) T* l = lhs.get(); U* r = rhs.get(); - // 改为直接比较指针,而不是比较值 + // Compare pointers directly instead of comparing values of the two pointers. + // 改为直接比较指针,而不是比较值 return (l != r); } /** + * @brief Determine '<', can be used in map and other conrainers. * @brief 小于判断, 用于放在map等容器中. * * @param T @@ -448,7 +493,8 @@ inline bool operator<(const TC_AutoPtr& lhs, const TC_AutoPtr& rhs) U* r = rhs.get(); if(l && r) { - //return *l < *r; + // return *l < *r; + // Compare pointers directly instead of comparing values of the two pointers. // 改为直接比较指针,而不是比较值 return (l < r); } diff --git a/util/include/util/tc_base64.h b/util/include/util/tc_base64.h index 22e288e80851a976a0fcf79800d7c84ca31c2b95..321689654ccd5c6be46bc05f209cbe8422762fbc 100644 --- a/util/include/util/tc_base64.h +++ b/util/include/util/tc_base64.h @@ -25,21 +25,30 @@ namespace tars { ///////////////////////////////////////////////// /** -* @file tc_base64.h -* @brief base64编解码类. +* @file tc_base64.h +* @brief base64 Codec Class +* @brief base64编解码类. */ ///////////////////////////////////////////////// /** -* @brief 该类提供标准的Base64的编码解码 +* @brief This class provides standard base64 encoding and decoding methods. +* @brief 该类提供标准的base64的编码解码 */ class TC_Base64 { public: /** - * @brief 对字符串进行base64编码. - * + * @brief Encode the string by base64 + * @brief 对字符串进行base64编码. + * + * @param data Data to be encoded + * @param bChangeLine Add line breaks in the final encoded data if necessary, + * (In the RFC, it is recommended to add an 'Enter' after every 76 characters. + * No newline is added by default.) + * @return string the encoded data + * * @param data 需要编码的数据 * @param bChangeLine 是否需要在最终编码数据加入换行符 , * (RFC中建议每76个字符后加入回车换行,默认为不添加换行 @@ -48,16 +57,28 @@ public: static string encode(const string &data, bool bChangeLine = false); /** - * @brief 对字符串进行base64解码. - * + * @brief Decode the string by base64 + * @brief 对字符串进行base64解码. + * + * @param data Data to be decoded + * @return string the decoded data + * * @param data 需要解码的数据 * @return string 解码后的数据 */ static string decode(const string &data); /** - * @brief 对字符串进行base64编码. - * + * @brief Encode the string by base64 + * @brief 对字符串进行base64编码. + * + * @param buffer buffer pointer + * @param length length + * @param bChangeLine Add line breaks in the final encoded data if necessary, + * (In the RFC, it is recommended to add an 'Enter' after every 76 characters. + * No newline is added by default.) + * @return string the encoded data + * * @param buffer buffer指针 * @param length 长度 * @param bChangeLine 是否需要在最终编码数据加入换行符 , @@ -67,7 +88,16 @@ public: static string encode(const char *buffer, size_t length, bool bChangeLine = false); /** + * @brief Encode the string by base64 * @brief 对字符串进行base64编码 . + * + * @param pSrc the data to be encoded + * @param nSrcLen the length of the data to be encoded + * @param pDst the encoded data + * @param bChangeLine Add line breaks in the final encoded data if necessary, + * (In the RFC, it is recommended to add an 'Enter' after every 76 characters. + * No newline is added by default.) + * @return the length of the encoded string * * @param pSrc 需要编码的数据 * @param nSrcLen 需要编码的数据长度 @@ -79,8 +109,14 @@ public: static int encode(const unsigned char* pSrc, size_t nSrcLen, char* pDst, bool bChangeLine = false); /** - * @brief 对字符串进行base64解码. - * + * @brief Decode the string by base64 + * @brief 对字符串进行base64解码 + * + * @param pSrc the data to be decoded + * @param nSrcLe the length of the data to be decoded + * @param pDst the decoded data + * @return the length of the decoded string + * * @param pSrc 需要解码的数据 * @param nSrcLe 需要解码的数据长度 * @param pDst 解码后的数据 @@ -91,11 +127,13 @@ public: protected: /** - * base64编码表 + * base64 Code Table + * base64编码表 */ static const char EnBase64Tab[]; /** - * base64解码表 + * base64 Decode Table + * base64解码表 */ static const char DeBase64Tab[]; }; diff --git a/util/include/util/tc_bitmap.h b/util/include/util/tc_bitmap.h index 10896bb46654c060d47a416710c68279fc2e40be..babce72b20168765a56b41bdf1cee19cd3d64c31 100644 --- a/util/include/util/tc_bitmap.h +++ b/util/include/util/tc_bitmap.h @@ -29,10 +29,12 @@ namespace tars ///////////////////////////////////////////////// /** * @file tc_bitmap.h + * @brief Multi-bit Bitmap Class * @brief 多位bitmap类. */ ///////////////////////////////////////////////// /** + * @brief Exception * @brief 异常 */ struct TC_BitMap_Exception : public TC_Exception @@ -43,18 +45,25 @@ struct TC_BitMap_Exception : public TC_Exception /** - * @brief 内存bitmap,每个整数1位,可以支持多位,即几个整数多位. + * @brief Memory bitmap, 1 bit for each integer, can support multiple bits, + * that is, several bits for several integers. + * @brief 内存bitmap,每个整数1位,可以支持多位,即几个整数多位. * - * 操作过程不加锁,如果有需要在外面调用的时候加,通常采用群锁策略. + * The process of the operation will not be locked. + * If it needs to be locked when called outside, the group lock strategy is usually adopted. + * 操作过程不加锁,如果有需要在外面调用的时候加,通常采用群锁策略. * - * 注意群锁策略应该/8,然后按照尾号分群锁 + * Attention that according to the group lock strategy, + * memory block address should be divided by 8, + * and then lock the blocks group by the tail number. + * 注意群锁策略应该/8,然后按照尾号分群锁 */ class TC_BitMap { public: /** + * @brief the bitmap of memories, each integer holds 1 bit * @brief 内存的bitmap,每个整数保持1位 - * */ class BitMap { @@ -66,55 +75,85 @@ public: #define _clear_bit(n,m) (n&(~_magic_bits[m])) #define _get_bit(n,m) (n&_magic_bits[m]) + /**the Version of Shared Memories*/ /**共享内存版本*/ #define BM_VERSION 1 /** + * @brief Calculate the size of the required memory based on the number of elements. * @brief 根据元素个数计算需要内存的大小 - * @param iElementCount, 需要保存的元素个数(元素从0开始记) + * + * @param iElementCount The number of elements to be saved (marked start from 0) + * @param iElementCount 需要保存的元素个数(元素从0开始记) * * @return size_t */ static size_t calcMemSize(size_t iElementCount); /** + * @brief Initialize * @brief 初始化 + * + * @param pAddr Absolute address * @param pAddr 绝对地址 + * + * @param iSize size, calculated by (calcMemSize) * @param iSize 大小, 采用(calcMemSize)计算出来 - * @return 0: 成功, -1:内存不够 + * + * @return 0: success, -1: lack of memories + * @return 0: 成功, -1: 内存不够 */ void create(void *pAddr, size_t iSize); /** + * @brief Link to a memory block * @brief 链接到内存块 + * + * @param pAddr Address, calculated by (calcMemSize) * @param pAddr 地址, 采用(calcMemSize)计算出来 - * @return 0, 成功, -1,版本不对, -2:大小不对 + * + * @return 0:success, -1:wrong version, -2:wrong size + * @return 0:成功, -1:版本不对, -2:大小不对 + * */ int connect(void *pAddr, size_t iSize); /** + * @brief Whether it have mark or not * @brief 是否有标识 - * @param i + * + * @param i + * + * @return int, >0:marked, =0:no mark, <0:out of range * @return int, >0:有标识, =0:无标识, <0:超过范围 + * */ int get(size_t i); /** + * @brief Mark * @brief 设置标识 + * * @param i + * + * @return int, >0:marked, =0:no mark, <0:out of range * @return int, >0:有标识, =0:无标识, <0:超过范围 */ int set(size_t i); /** + * @brief Clear Marks * @brief 清除标识 + * * @param i * + * @return int, >0:marked, =0:no mark, <0:out of range * @return int, >0:有标识, =0:无标识, <0:超过范围 */ int clear(size_t i); /** + * @brief Clear all data * @brief 清除所有的数据 * * @return int @@ -122,6 +161,7 @@ public: int clear4all(); /** + * @brief Dump to File * @brief dump到文件 * @param sFile * @@ -130,104 +170,168 @@ public: int dump2file(const string &sFile); /** + * @brief Load from File * @brief 从文件load + * * @param sFile * * @return int */ int load5file(const string &sFile); + /**the Head of Shared Memories*/ /**共享内存头部*/ #pragma pack(1) struct tagBitMapHead { - char _cVersion; /**版本, 当前版本为1*/ - size_t _iMemSize; /**共享内存大小*/ + char _cVersion; /**version, the current version is 1*/ + /**版本, 当前版本为1*/ + size_t _iMemSize; /**the size of the shared memory*/ + /**共享内存大小*/ }; #pragma pack() /** - * @brief 获取头部地址 + * @brief get the address of the head + * @brief 获取头部地址 + * + * @return tagBitMapHead* the head of the shared memory * @return tagBitMapHead* 共享内存头部 */ BitMap::tagBitMapHead *getAddr() const { return _pHead; } /** - * @brief 获取内存大小 + * @brief get the size of the memory + * @brief 获取内存大小 + * + * @return the size of the memory * @return 内存大小 + * */ size_t getMemSize() const { return _pHead->_iMemSize; } protected: /** + * the Head of the Shared Memory * 共享内存头部 */ tagBitMapHead *_pHead; /** + * pointer of a data block * 数据块指针 */ unsigned char * _pData; }; /** + * @brief Calculate the memory size according to count the number of the elements. * @brief 根据元素个数计算需要内存的大小 + * + * @param iElementCount the number of the elements which needs to be saved(marked started from 0) * @param iElementCount 需要保存的元素个数(元素从0开始记) - * @param iBitCount 每个元素支持几位(默认1位) (位数>=1) + * + * @param iBitCount the max bit value of each element(defualt for 1 bit)(each bit>=1) + * @param iBitCount 每个元素支持几位(默认1位) (位数>=1) + * + * @return the required size of the memory * @return 所需内存的大小 + * */ static size_t calcMemSize(size_t iElementCount, unsigned iBitCount = 1); /** + * @brief Initialize * @brief 初始化 + * + * @param pAddr Absolute Address * @param pAddr 绝对地址 + * + * @param iSize Size, Calculate by (calcMemSize) * @param iSize 大小, 采用(calcMemSize)计算出来 + * + * @return 0: success, -1:lack of memories * @return 0: 成功, -1:内存不够 + * */ void create(void *pAddr, size_t iSize, unsigned iBitCount = 1); /** + * @brief Link to Memory Blocks * @brief 链接到内存块 + * + * @param pAddr Address, Calculate by (calcMemSize) * @param pAddr 地址,采用(calcMemSize)计算出来 + * + * @return 0:success, -1:wrong version, -2:wrong size * @return 0:成功, -1:版本不对, -2:大小不对 + * */ int connect(void *pAddr, size_t iSize, unsigned iBitCount = 1); /** - * @brief 是否有标识 + * @brief Whether it is Marked or not + * @brief 是否有标识 + * + * @param i the value of the element * @param i 元素值 - * @param iBit 第几位 + * + * @param iBit bit number + * @param iBit 第几位 + * + * @return int, >0:maked, =0:no mark, <0:out of range * @return int, >0:有标识, =0:无标识, <0:超过范围 + * */ int get(size_t i, unsigned iBit = 1); /** + * @brief Mark * @brief 设置标识 + * + * @param i the value of the element * @param i 元素值 - * @param iBit 第几位 + * + * @param iBit bit number + * @param iBit 第几位 + * + * @return int, >0:marked, =0:no mark, <0:outof range * @return int, >0:有标识, =0:无标识, <0:超过范围 + * */ int set(size_t i, unsigned iBit = 1); /** + * @brief Clear a mark * @brief 清除标识 + * + * @param i the value of the element * @param i 元素值 + * + * @param iBit bit number * @param iBit 第几位 + * + * @return int, >0:marked, =0:no mark, <0:out of range * @return int, >0:有标识, =0:无标识, <0:超过范围 */ int clear(size_t i, unsigned iBit = 1); /** + * @brief Clear all marks * @brief 清除所有的标识 * + * @param iBit bit number * @param iBit 第几位 + * * @return int */ int clear4all(unsigned iBit = (unsigned)(-1)); /** + * @brief Dump to File * @brief dump到文件 + * * @param sFile * * @return int @@ -235,7 +339,9 @@ public: int dump2file(const string &sFile); /** + * @brief Load from File * @brief 从文件load + * * @param sFile * * @return int diff --git a/util/include/util/tc_cas_queue.h b/util/include/util/tc_cas_queue.h index 6d6bc8baa29360600c4d4cc04e2c60a44100ef1f..fe730e189bf0c6ab5f1c0829cb13a7304ee00b10 100755 --- a/util/include/util/tc_cas_queue.h +++ b/util/include/util/tc_cas_queue.h @@ -14,6 +14,7 @@ namespace tars ///////////////////////////////////////////////// /** * @file tc_cas_queue.h + * @brief Lock-Free Thread * @brief 线程无锁 * * @author ruanshudong@qq.com @@ -21,6 +22,7 @@ namespace tars ///////////////////////////////////////////////// /** + * @brief Thread Safe Queue * @brief 线程安全队列 */ template > @@ -34,80 +36,96 @@ public: typedef D queue_type; /** - * @brief 从头部获取数据, 没有数据则等待. + * @brief Getting data from the head without data throwing exception + * @brief 从头部获取数据, 没有数据抛出异常 * * @param t - * @return bool: true, 获取了数据, false, 无数据 + * @return bool: true, get data ; false, no data + * @return bool: true, 获取了数据, false, 无数据 */ T front(); /** - * @brief 从头部获取数据, 没有数据则等待. + * @brief Get data from the head + * @brief 从头部获取数据 * * @param t + * @return bool: true, get data ; false, no data * @return bool: true, 获取了数据, false, 无数据 */ bool pop_front(T& t); /** - * @brief 从头部获取数据, 没有数据则等待. + * @brief Get data from the head + * @brief 从头部获取数据 * - * @return bool: true, 获取了数据, false, 无数据 + * @return bool: true, get data ; false, no data + * @return bool: true, 获取了数据, false, 无数据 */ bool pop_front(); /** - * @brief 放数据到队列后端. + * @brief Put data to the back end of the queue. + * @brief 放数据到队列后端. * * @param t */ void push_back(const T& t); /** - * @brief 放数据到队列后端. + * @brief Put data to the back end of the queue. + * @brief 放数据到队列后端. * * @param vt */ void push_back(const queue_type &qt); /** - * @brief 放数据到队列前端. + * @brief Put data to the front end of the queue. + * @brief 放数据到队列前端. * * @param t */ void push_front(const T& t); /** - * @brief 放数据到队列前端. + * @brief Put data to the front end of the queue. + * @brief 放数据到队列前端. * * @param vt */ void push_front(const queue_type &qt); /** - * @brief 交换数据 + * @brief Exchange Data + * @brief 交换数据 * * @param q + * @return bool: true, data returned ; false, no data returned * @return 有数据返回true, 无数据返回false */ bool swap(queue_type &q); /** + * @brief Size of the Queue * @brief 队列大小. * + * @return size_t the size of the queue * @return size_t 队列大小 */ size_t size() const; /** + * @brief Clear Up the Queue * @brief 清空队列 */ void clear(); /** * @brief 是否数据为空. - * + * @brief Determine whether the data is null or not. * @return bool 为空返回true,否则返回false + * @return bool: true, is null ; false, not null */ bool empty() const; @@ -120,15 +138,17 @@ protected: protected: /** * 队列 + * Queue */ queue_type _queue; /** * 队列长度 + * The length of a queue */ size_t _size; - //锁 + //锁Lock TC_SpinLock _mutex; }; diff --git a/util/include/util/tc_cgi.h b/util/include/util/tc_cgi.h index e4860571d783f961ed278a2f49bec42e9bd6e258..9322237a7f53bfae5e8957f54a330440290c57b8 100644 --- a/util/include/util/tc_cgi.h +++ b/util/include/util/tc_cgi.h @@ -29,6 +29,8 @@ namespace tars /** * @file tc_cgi.h * @brief CGI处理类 +* @brief CGI Processing Class + */ ///////////////////////////////////////////////// class TC_Cgi; @@ -37,6 +39,7 @@ class TC_HttpRequest; /** * @brief 配置文件异常类 +* @brief Profile Exception Class */ struct TC_Cgi_Exception : public TC_Exception { @@ -48,11 +51,14 @@ struct TC_Cgi_Exception : public TC_Exception /** * @brief 全局的友元函数,定义该函数, * 则可以用TC_Common::tostr对 vector进行输出操作 +* @brief Global Friend. +* By defining this function, you can use TC_Common::tostr to output vector */ ostream &operator<<(ostream &os, const TC_Cgi_Upload &tcCgiUpload); /** * @brief cgi上传文件操作,通过该类获取cgi上传的文件信息 +* @brief CGI Uploaded File Operation, you can get cgi uploaded file info from this class. */ class TC_Cgi_Upload { @@ -61,6 +67,7 @@ public: /** * @brief 构造函数 + * @brief Constructor */ TC_Cgi_Upload() :_sFileName("") @@ -73,26 +80,30 @@ public: /** * @brief 拷贝构造函数. + * @brief Copy Constructor */ TC_Cgi_Upload(const TC_Cgi_Upload &tcCgiUpload); /** * @brief 赋值构造函数 + * @brief Assignment Constructor */ TC_Cgi_Upload & operator=(const TC_Cgi_Upload &tcCgiUpload); /** * @brief 获取上传的信息. - * - * return 上传文件的信息 + * @brief Get Uploaded Info + * @return 上传文件的信息 + * @return Uploaded File Info */ string tostr() const; /** * @brief 获取客户端IE INPUT上传控件的名称. - * - * return INPUT上传控件名称 + * @brief Get the Client IE ; Input the name of the upload control + * @return INPUT上传控件名称 + * @return INPUT the name of the upload control */ string getFormFileName() const { @@ -101,8 +112,9 @@ public: /** * @brief 返回INPUT控件用户输入的名称,及客户端真实的文件名称. - * - * return 客户端真实的文件名称 + * @brief Return the name from the imput control and the real file name from the Client. + * @return 客户端真实的文件名称 + * @return the real file name from the Client */ string retRealFileName() const { @@ -111,8 +123,9 @@ public: /** * @brief 上传到服务器后,服务器端文件名称. - * - * return 服务器端文件名称 + * @brief The server file name after uploading to the server. + * @return 服务器端文件名称 + * @return the file name from the Server. */ string getSeverFileName() const { @@ -121,8 +134,9 @@ public: /** * @brief 获取上传的文件大小. - * - * return size_t类型,上传的文件大小 + * @brief Get the size of the uploaded file. + * @return size_t类型,上传的文件大小 + * @return size_t : the size of the uploaded file */ size_t getFileSize() const { @@ -131,8 +145,9 @@ public: /** * @brief 上传的文件是否超过大小. - * - * return 超过大小返回true,否则返回false + * @brief Determine whether the size of the uploaded file is oversize or not. + * @return 超过大小返回true,否则返回false + * @return bool: oversize, true ; not oversize, false */ bool isOverSize() const { @@ -143,26 +158,31 @@ protected: /** * 上传文件,浏览器file控件名称 + * Upload files,the name of the file control on the browser. */ string _sFileName; /** * 上传文件真实名称,客户端的文件名称 + * the real name of the uploaded file, the name of the file on the Client. */ string _sRealFileName; /** * 上传文件服务器端名称 + * the name of the server which uploaded the file */ string _sServerFileName; /** * 上传文件大小,字节数 + * the size of the uploaded file, Bytes */ size_t _iSize; /** * 上传文件是否超过大小 + * whether the uploaded file is oversize or not */ bool _bOverSize; @@ -171,25 +191,29 @@ protected: /** * @brief cgi操作相关类. +* @brief CGI Operation Related Classes * * 主要操作包括: -* +* Main includes: * 1 支持参数解析 -* +* 1 Support parameter resolution * 2 支持cookies解析 -* +* 2 Support cookies resolution * 3 支持文件上传,设置上传文件的最大个数,文件的最大大小 -* +* 3 Support file uploading, setting the max number of uploaded files and the max size of a file. * 4 上传文件时, 需要检查文件是否超过最大大小 -* +* 4 When uploading files, you need to check whether the files are oversize or not. * 5 上传文件时, 需要检查上传文件个数是否限制 -* +* 5 When uploading files, you need to check +* whether the number of the uploaded files is limited. * 说明:多个文件同时上传时,浏览器的file控件必须取不同name,否则将无法正确的上传文件 -* +* Notes : When multiple files are uploaded at the same time, +* the browser's file control must take a different name, +* otherwise the file will not be uploaded correctly. * 注意:调用parseCgi解析标准输入, -* +* Atttention : When calling parseCgi to parse the standard input, * 如果有文件上传需要调用setUpload, 并且需要在parseCgi之前调用 -* +* setUpload, which is called by the uploaded files, needs to be called before parseCgi. */ class TC_Cgi { @@ -197,16 +221,19 @@ public: /** * @brief TC_Cgi构造函数 + * @brief TC_Cgi Constructor */ TC_Cgi(); /** * @brief 析构函数 + * @brief Destructor */ virtual ~TC_Cgi(); /** * @brief 定义环境变量 + * @brief Define the environment variables */ enum { @@ -232,51 +259,68 @@ public: }; /** - * @brief 设置上传文件. + * @brief 设置上传文件. + * @brief Set the uploaded file. * * @param sUploadFilePrefix, 文件前缀(包含路径), 如果有文件上传,则文件保存在以该前缀为名称的路径下 * 如果有多个文件上传,则文件名称以次在后面加"_序号" + * The file prefix (includes its path). If a file is uploaded, the file is saved in the path with the prefix as the name. + * If more than one file is uploaded, then the file name will be followed by "_ No." + * * @param iMaxUploadFiles 最多上传文件个数,<0:没有限制 + * Maximum number of uploaded files, if iMaxUploadFiles < 0 : no limit + * * @param iUploadMaxSize 每个文件上传的最大大小(字节) + * Maximum size uploaded per file (Bytes) */ void setUpload(const string &sUploadFilePrefix, int iMaxUploadFiles = 5, size_t iUploadMaxSize = 1024*1024*10, size_t iMaxContentLength = 1024*1024*10); /** * @brief 从标准输入解析cgi. + * @brief Analyze CGI from standard input */ void parseCgi(); /** * @brief 直接从http请求解析. + * @brief Request parsing directly from http. * * @param request http请求 + * @param request http request */ void parseCgi(const TC_HttpRequest &request); /** * @brief 获取cgi的url参数multimap. + * @brief Get the URL parameter of CGI : Multimap * - * @return multimapcgi的url参数 + * @return multimap cgi的url参数 + * @return multimap the URL parameter of CGI */ const multimap &getParamMap() const; /** * @brief 获取cgi环境变量map. + * @brief Get CGI environment variable: Map * - * @return mapcgi的环境变量 + * @return map cgi的环境变量 + * @return map the environment variable of CGI */ map getEnvMap() const { return _env; } /** * @brief 获取cgi的参数map, 将multimap转换成map返回 * , 对于一个参数名称对应多个参数值的情况, 只取其中一个值. - * + * @brief Get the CGI parameter, map, and convert Multimap to Map as return. + * If a parameter name corresponds to more than one parameter value, only one value is taken. + * * @return map */ map getParamMapEx() const; /** * @brief 获取cookies的参数map. + * @brief Get cookies' parameter : map * * @return map */ @@ -284,165 +328,203 @@ public: /** * @brief 获取cgi的某个参数. + * @brief Get a certain parameter from CGI * - * @param sName 参数名称 + * @param sName 参数名称 parameter name * @return */ string &operator[](const string &sName); /** * @brief 获取cgi的某个参数. + * @brief Get a certain parameter from CGI * - * @param sName 参数名称 - * @return 参数的值 + * @param sName 参数名称 parameter name + * @return 参数的值 the value of the parameter */ string getValue(const string& sName) const; /** * @brief 获取某一名称的参数的多个值. + * @brief Get multiple values of a parameter with a name. * * 用于解析checkbox这类控件的值( 一个参数名,多个参数值) - * @param sName 参数名称 - * @param vtValue 该名称的参数值组成的vector - * @return vector, 该名称的参数值组成的vector + * This is used to parse the value of a control such as a checkbox (one parameter name, multiple parameter values) + * @param sName 参数名称 / the parameter name + * @param vtValue 该名称的参数值组成的vector / vector composed of the parameter value of the name + * @return vector, 该名称的参数值组成的vector + * @return vector vector composed of the parameter value of the name */ const vector &getMultiValue(const string& sName, vector &vtValue) const; /** * @brief 获取cookie值. + * @brief Get the cookie value. * - * @param sName cookie名称 - * @return string类型的cookie值 + * @param sName cookie名称 / the name of the cookie + * @return string类型的cookie值 / Cookie value of type string */ string getCookie(const string& sName) const; /** * @brief 设置cookie值. + * @brief Set cookie value. * - * @param sName cookie名称 - * @param sValue cookie值 - * @param sExpires 过期日期 - * @param sPath cookie有效路径 - * @param sDomain cookie有效域 - * @param bSecure 是否安全(ssl时有效) - * @return 返回字符串,代表cookie值 + * @param sName cookie名称 / cookie name + * @param sValue cookie值 / cookie value + * @param sExpires 过期日期 / the expire date + * @param sPath cookie有效路径 / cookie valid path + * @param sDomain cookie有效域 / cookie valid domain + * @param bSecure 是否安全(ssl时有效) / Whether it is secure (valid in SSL) + * @return 返回字符串,代表cookie值 / returns a string which representing the cookie value */ string setCookie(const string &sName, const string &sValue, const string &sExpires="", const string &sPath="/", const string &sDomain = "", bool bSecure = false); /** * @brief 参数链表是否为空. + * @brief Whether the parameter list is empty. * * @return 参数链表为空返回true,否则返回false + * @return bool : true, the parameter list is empty ; false, the parameter list is not empty */ bool isParamEmpty() const; /** * @brief 参数是否存在. + * Wether the parameter exists or not. * - * @param sName 参数名称 - * @return 存在返回true,否则返回false + * @param sName 参数名称 / the parameter name + * @return 存在返回true,否则返回false / if exists retrun true, else return false. */ bool isParamExist(const string& sName) const; /** * @brief 上传文件是否超过大小,多个文件上传时, * 只要有一个文件超过大小,则超过 + * Wheter the size of the uploaded file is scale out. + * When uploading multiple files, it is scale out as long as there's one file exceeds the size. * @return 按照以上标准超过大小的返回true,否则返回false + * According to the standard above, if it is oversize, return true, else return false. */ bool isUploadOverSize() const; /** * @brief 上传文件是否超过大小,多个文件上传时, * 只要有一个文件超过大小,则超过 + * Wheter the size of the uploaded file is scale out. + * When uploading multiple files, it is scale out as long as there's one file exceeds the size. * @param vtUploads 返回超过大小的文件名称(浏览器file控件的名称) + * Returns the name of a file larger than the size (the name of the browser file control) * @return 按照以上标准超过大小的返回true,否则返回false + * According to the standard above, if it is oversize, return true, else return fals. */ bool isUploadOverSize(vector &vtUploads) const; /** * @brief 是否超过上传文件个数. + * Wheter the number of uploaded files exceeds. * * @return 超过上传个数返回true,否则返回false + * bool : true, the number of the uploaded files exceeds ; false, else */ bool isOverUploadFiles() const { return _bOverUploadFiles; } /** * @brief 获取上传文件个数. + * Get the number of uploaded files * * @return size_t上传文件的个数 + * size_t the number of uploaded files */ size_t getUploadFilesCount() const; /** * @brief 获取上传文件的相关信息 + * Get the related info about the uploaded files * * @return map结构中, * 保存文件名和文件相关信息的map + * In the structure map, + * the map which stored the file name and the file's related information. */ const map &getUploadFilesMap() const; /** * @brief 获取环境变量. + * Get the environment variables * - * @param iEnv 枚举变量 - * @return 环境变量 + * @param iEnv 枚举变量 / Enumerating variables + * @return 环境变量 / Environment variables */ string getCgiEnv(int iEnv); /** * @brief 获取环境变量. + * Get the environment variables * - * @param sEnv 环境变量名称 - * @return 环境变量的值 + * @param sEnv 环境变量名称 / the environment variable name + * @return 环境变量的值 / the envitonment variable name */ string getCgiEnv(const string& sEnv); /** * @brief 设置环境变量. + * Set environment variales * - * @param sName 环境变量名称 - * @param sValue 环境变量的值 + * @param sName 环境变量名称 / environment variable name + * @param sValue 环境变量的值 / environment variable value */ void setCgiEnv(const string &sName, const string &sValue); /** * @brief 返回html头,content-type . + * Return HTML header, content type * - * @param sHeader 缺省值为"text/html" + * @param sHeader 缺省值为"text/html" + * The default value is "text / HTML" * @return */ + static string htmlHeader(const string &sHeader = "text/html"); /** * @brief http请求的url解码, %后面的换成字符. - * - * @param sUrl http请求url - * @return 解码后的字符串 + * The URL of the HTTP request is decoded and the one after% is replaced with a character. + * + * @param sUrl http请求url / HTTP request URL + * @return 解码后的字符串 / the encoded string */ static string decodeURL(const string &sUrl); /** * @brief 对url进行编码, 非数字和字母用%XX代替. - * - * @param sUrl http请求url - * @return 编码后的url + * Encode the URL with% XX instead of numbers and letters. + * + * @param sUrl http请求url / HTTP request URL + * @return 编码后的url / the encoded string */ static string encodeURL(const string &sUrl); /** * @brief 对源字符串进行HTML编码(<>"&) - * + * HTML encoding of the source string (< > "& '). + * + * the source string * @param src 源字符串 - * @param blankEncode 是否对空格也编码(空格, \t, \r\n, \n) + * + * Whether encoding the 'space' (space, \t, \r\n, \n) + * @param blankEncode 是否对空格也编码(空格, \t, \r\n, \n) + * + * HTML encoded string * @return HTML编码后的字符串 */ static string encodeHTML(const string &src, bool blankEncode = false); /** * @brief 对源字符串进行XML编码(<>"&'). - * - * @param src 源字符串 - * @return XML编码后的字符串 + * XML encoding of the source string (< > "& '). + * @param src 源字符串 / Source string + * @return XML编码后的字符串 / XML encoded string */ static string encodeXML(const string &src); @@ -450,13 +532,14 @@ protected: /** * @brief 申明,但是不定义,保证这个函数不会被使用 + * Declare, but do not define, to ensure that this function will not be used. */ TC_Cgi &operator=(const TC_Cgi &tcCgi); /** * @brief GET method. * - * @param sBuffer GET的QueryString + * @param sBuffer GET的QueryString / the QueryString of GET * return */ void getGET(string &sBuffer); @@ -464,60 +547,65 @@ protected: /** * @brief POST method. * - * @param sBuffer POST的QueryString + * @param sBuffer POST的QueryString / the QueryString of POST * return */ void getPOST(string &sBuffer); /** - * @brief 解析文件上传. + * @brief 解析文件上传. + * Parsing file upload * - * @param mmpParams [out]输出参数multimap + * @param mmpParams [out]输出参数multimap / output multimap * return */ void parseUpload(multimap &mmpParams); /** * @brief 解析form数据 + * Parsing form data */ void parseFormData(multimap &mmpParams, const string &sBoundary); /** * @brief 忽略空行 + * Ignore empty lines */ void ignoreLine(); /** * @brief 写文件. - * - * @param sFileName 文件名称 - * @param sBuffer 要写入的内容 + * Write File + * @param sFileName 文件名称 / file name + * @param sBuffer 要写入的内容 / contents needs to be wrote. */ bool writeFile(FILE*fp, const string &sFileName, const string &sBuffer, size_t &iTotalWrite); /** * @brief 非上传模式下解析. - * - * @param mmpParams [out]输出参数multimap - * @param sBuffer [in]输入QueryString + * Analysis in non upload mode + * @param mmpParams [out]输出参数multimap / output multimap + * @param sBuffer [in]输入QueryString / output QueryString * return */ void parseNormal(multimap &mmpParams, const string& sBuffer); /** * @brief 解析cookies. + * Parsing cookies * - * @param mpCooies [out]输出cookiesmap - * @param sBuffer [in]输入Cookies字符串 + * @param mpCooies [out]输出cookiesmap / output mpCookies + * @param sBuffer [in]输入Cookies字符串/ input string Cookies * return */ void parseCookies(map &mpCooies, const string& sBuffer); /** * @brief 控制解析cgi input的基本流程. + * Control the basic process of parsing CGI input * - * @param mmpParams [out]输出参数 multimap - * @param mpCooies [out]输出cookies + * @param mmpParams [out]输出参数 multimap / output multimap + * @param mpCooies [out]输出cookies / output multimap * return */ void readCgiInput(multimap &mmpParams, map &mpCooies); @@ -531,21 +619,25 @@ protected: /** * 流 + * Stream */ istringstream _iss; /** * 读入 + * Read in */ istream *_is; /** * 环境变量 + * environmet variable */ map _env; /** * cgi参数 + * CGI parameter */ multimap _mmpParams; @@ -556,36 +648,43 @@ protected: /** * 上传文件名称前缀 + * Upload file name prefix */ string _sUploadFilePrefix; /** * 上传文件的最大个数,<0:无限制 + * Maximum number of uploaded files, < 0: Unlimited */ int _iMaxUploadFiles; /** * 上传文件的最大大小 + * Maximum size of uploaded file */ size_t _iUploadMaxSize; /** * 是否超过上传文件个数 + * Whether the number of the uploaded file is exceeded. */ bool _bOverUploadFiles; /** * 最大的content-length + * the max content-length */ size_t _iMaxContentLength; /** * 是否超过大小,有一个文件超过则超过 + * Determine whether the file is oversize or not, as long as one file is oversize that _bUploadFileOverSize is ture */ bool _bUploadFileOverSize; /** * 上传文件相关信息保存在该map中 + * the related infomation about the uploaded files is stored in this map */ map _mpUpload; }; diff --git a/util/include/util/tc_clientsocket.h b/util/include/util/tc_clientsocket.h index ff0225dea398a79142a5e7d2201040bf32881f86..b5d6d1f445bd3b06efb6680f77daf7a0027d56d6 100644 --- a/util/include/util/tc_clientsocket.h +++ b/util/include/util/tc_clientsocket.h @@ -28,10 +28,12 @@ namespace tars /** * @file tc_clientsocket.h * @brief 客户端发包收包类. + * @brief Client Contracting and Receiving Class */ ///////////////////////////////////////////////// /** * @brief 解析endpoint异常类 +* @brief Parsing endpoint Exception Class */ struct TC_EndpointParse_Exception : public TC_Exception { @@ -41,6 +43,7 @@ struct TC_EndpointParse_Exception : public TC_Exception /** * @brief 表示一个网络端口,支持以下格式: + * @brief Represents a network port which supports the following formats: * * 1:tcp -h 127.0.0.1 -p 2345 -t 10000 * @@ -49,10 +52,13 @@ struct TC_EndpointParse_Exception : public TC_Exception * 3:udp -h 127.0.0.1 -p 2345 -t 10000 * * -p 0:表示本地套接字 - * + * -p 0:Represents a local socket + * * -q 0:表示qos的dscp值 - * + * -q 0:Represents the DSCP value of QoS + * * 此时-h表示的文件路径 + * At this time, the file path is represented by '-h' */ class TC_Endpoint { @@ -65,10 +71,13 @@ public: /** * @brief 构造函数 + * @brief Constructor * @param host * @param port * @param timeout, 超时时间, 毫秒 + * @param timeout, timeoput, unit : ms * @param type, SOCK_STREAM或SOCK_DGRAM + * @param type, SOCK_STREAM or SOCK_DGRAM */ TC_Endpoint(const string& host, int port, int timeout, EType type = TCP, int grid = 0, int qos = 0, int weight = -1, unsigned int weighttype = 0, int authType = 0) { @@ -77,6 +86,7 @@ public: /** * @brief 用字符串描述来构造 + * @brief Use string to describe the constructor * @param desc */ TC_Endpoint(const string& desc) @@ -86,6 +96,7 @@ public: /** * @brief 拷贝构造 + * @brief Copy Constructor * @param l */ TC_Endpoint(const TC_Endpoint& l) @@ -104,6 +115,7 @@ public: /** * @brief 赋值函数 + * @brief Assignment Function * @param l * * @return TC_Endpoint& @@ -142,12 +154,14 @@ public: /** * @brief 设置ip + * @brief Set IP * @param str */ void setHost(const string& host) { _host = host; _isIPv6 = TC_Socket::addressIsIPv6(_host); } /** * @brief 获取ip + * @brief Get IP * * @return const string& */ @@ -155,12 +169,14 @@ public: /** * @brief 设置端口 + * @brief Set Port * @param port */ void setPort(int port) { _port = port; } /** * @brief 获取端口 + * @brief Get Port * * @return int */ @@ -168,12 +184,14 @@ public: /** * @brief 设置超时时间 + * @brief Set Timeout * @param timeout */ void setTimeout(int timeout) { _timeout = timeout; } /** * @brief 获取超时时间 + * @brief Get Timeout * * @return int */ @@ -181,6 +199,7 @@ public: /** * @brief 是否是TCP, 否则则为UDP + * @brief Determine whether it uses TCP or UDP * * @return bool */ @@ -188,6 +207,7 @@ public: /** * @brief 是否是SSL + * @brief Whether it uses SSL * * @return int */ @@ -195,6 +215,7 @@ public: /** * @brief 设置为TCP或UDP + * @brief Set to TCP or UDP * @param bTcp */ int isUdp() const { return _type == UDP; } @@ -202,55 +223,65 @@ public: /** * @brief 设置为TCP/UDP/SSL + * @brief Set to TCP/UDP/SSL * @param type */ void setType(EType type) { _type = type; } /** * @brief 获取协议类型 + * @brief Get the protocol type */ EType getType() const { return _type; } /** * @brief 获取路由状态 + * @brief Get route status * @param grid */ int getGrid() const { return _grid; } /** * @brief 设置路由状态 + * @brief Set route status * @param grid */ void setGrid(int grid) { _grid = grid; } /** * @brief 获取路由状态 + * @brief Get route status * @param grid */ int getQos() const { return _qos; } /** * @brief 设置路由状态 + * @brief Set route status * @param grid */ void setQos(int qos) { _qos = qos; } /** * @brief 获取节点的静态权重值 + * @brief Get static weight value of node */ int getWeight() const { return _weight; } /** * @brief 设置节点的静态权重值 + * @brief Set static weight value of node * @param weight */ void setWeight(int weight) { _weight = weight; } /** * @brief 获取节点的权重使用方式 + * @brief Get the weight usage of nodes */ unsigned int getWeightType() const { return _weighttype; } /** * @brief 设置节点的权重使用方式 + * @brief Set the weight usage of nods * @param weightway */ void setWeightType(unsigned int weighttype) { _weighttype = weighttype; } @@ -258,6 +289,7 @@ public: #if TARGET_PLATFORM_LINUX || TARGET_PLATFORM_IOS /** * @brief 是否是本地套接字 + * @brief Whether it is a local socket or not * * @return bool */ @@ -272,16 +304,19 @@ public: /** * @brief 获取认证类型 + * @brief Get authentication type */ int getAuthType() const { return _authType; } /** * @brief 设置认证类型 + * @brief Set authentication type */ void setAuthType(int type) { _authType = type; } /** * @brief 字符串描述 + * @brief the string description * * @return string */ @@ -306,6 +341,7 @@ public: /** * @brief 字符串形式的端口 + * @brief Port in string * tcp:SOCK_STREAM * * udp:SOCK_DGRAM @@ -313,10 +349,13 @@ public: * -h: ip * * -p: 端口 + * -p: port * * -t: 超时时间, 毫秒 + * -t: timeout, unit:ms * * -p 和 -t可以省略, -t默认10s + * -p and -t can be omitted, -t defaults to 10s * * tcp -h 127.0.0.1 -p 2345 -t 10000 * @@ -335,40 +374,48 @@ protected: /** * 端口 + * Port */ int _port; /** * 超时时间 + * Timeout */ int _timeout; /** * 类型 + * Type */ EType _type; /** * 路由状态 + * Route Status */ int _grid; /** - * 网络Qos的dscp值 + * 网络QoS的dscp值 + * DSCP value of network QoS */ int _qos; /** * 节点的静态权重值 + * the static weight value of node */ int _weight; /** * 节点的权重使用方式 + * the weight usage of nodes */ unsigned int _weighttype; /** * 鉴权类型 + * Authentication Type */ int _authType; @@ -382,6 +429,7 @@ protected: /** * @brief 客户端socket相关操作基类 +* @brief Client Socket Related Operation Base Class */ class TC_ClientSocket { @@ -389,69 +437,98 @@ public: /** * @brief 构造函数 + * @brief Constructor */ TC_ClientSocket(); /** * @brief 析够函数 + * @brief Desturctor */ virtual ~TC_ClientSocket(); /** * @brief 构造函数 + * @brief Constructor * @param sIP 服务器IP + * @param sIP Server IP * @param iPort 端口, port为0时:表示本地套接字此时ip为文件路径 + * @param iPort Port, when port==0 : represent the local socket, and the IP is the file path this momnet * @param iTimeout 超时时间, 毫秒 + * @param iTimeout timeout, unit: ms */ TC_ClientSocket(const string &sIp, int iPort, int iTimeout) { init(sIp, iPort, iTimeout); } /** * @brief 初始化函数 + * @brief Initialize Function * @param sIP 服务器IP + * @param sIP Server IP * @param iPort 端口, port为0时:表示本地套接字此时ip为文件路径 + * @param iPort Port, when port==0 : represent the local socket, and the IP is the file path this momnet * @param iTimeout 超时时间, 毫秒 + * @param iTimeout timeout, unit: ms */ void init(const string &sIp, int iPort, int iTimeout); /** * @brief 发送到服务器 + * @brief Send to the Server * @param sSendBuffer 发送buffer + * @param sSendBuffer send buffer * @param iSendLen 发送buffer的长度 + * @param iSendLen send the buffer length * @return int 0 成功,<0 失败 + * @return int: 0 success, <0 fail */ virtual int send(const char *sSendBuffer, size_t iSendLen) = 0; /** * @brief 从服务器返回不超过iRecvLen的字节 + * @brief Return no more than iRecvLen bytes from the server * @param sRecvBuffer 接收buffer + * @param sRecvBuffer Receive buffer * @param iRecvLen 指定接收多少个字符才返回,输出接收数据的长度 + * @param iRecvLen Specify how many characters to receive before returning, and output the length of received data * @return int 0 成功,<0 失败 + * @return int: 0 success, <0 fail */ virtual int recv(char *sRecvBuffer, size_t &iRecvLen) = 0; /** * 关闭连接 + * Close Connection */ virtual void close(); /** * 获取socket + * Get socket * @return */ TC_Socket *getSocket() { return &_socket; } /** * @brief 定义发送的错误 + * @brief Define errors about sending */ enum EM_CIENT_SOCKET_TYPE { + /**EM_SUCCESS:Send Successfully**/ EM_SUCCESS = 0, /** EM_SUCCESS:发送成功*/ + /**EM_SEND:Send Error**/ EM_SEND = -1, /** EM_SEND:发送错误*/ + /**EM_SELECT:SELECT Error**/ EM_SELECT = -2, /** EM_SELECT:select 错误*/ + /**EM_TIMEOUT:SELECT Timeout**/ EM_TIMEOUT = -3, /** EM_TIMEOUT:select超时*/ + /**EM_RECV:RECEIVE Error**/ EM_RECV = -4, /** EM_RECV: 接受错误*/ + /**EM_CLOSE:Server Proactive Shutdown **/ EM_CLOSE = -5, /**EM_CLOSE: 服务器主动关闭*/ + /**EM_CONNECT:Server Connection Failed**/ EM_CONNECT = -6, /** EM_CONNECT : 服务器连接失败*/ + /**EM_SOCKET : SOCKET Initialize Failed**/ EM_SOCKET = -7 /**EM_SOCKET : SOCKET初始化失败*/ }; @@ -460,47 +537,59 @@ protected: /** * 套接字句柄 + * Socket Handle */ TC_Socket _socket; /** * ip或文件路径 + * IP or File Path */ string _ip; /** - * 端口或-1:标示是本地套接字 + * 端口或-1:表示是本地套接字 + * Port or - 1: indicates a local socket */ int _port; /** * 超时时间, 毫秒 + * Timeout, unit: ms */ int _timeout; /** * 是否是IPv6 + * Whether it is IPV6 or not */ bool _isIPv6 = false; }; /** * @brief TCP客户端Socket + * @brief TCP Client Socket * 多线程使用的时候,不用多线程同时send/recv,小心串包; + * When using multithreading, do not send/recv at the same time, and be careful of mixing packets; */ class TC_TCPClient : public TC_ClientSocket { public: /** * @brief 构造函数 + * @brief Constructor */ TC_TCPClient(){} /** * @brief 构造函数 + * @brief Constructor * @param sIp 服务器Ip + * @param sIp Server IP * @param iPort 端口 + * @param iPort Port * @param iTimeout 超时时间, 毫秒 + * @param iTimeout Timeout, unit: ms */ TC_TCPClient(const string &sIp, int iPort, int iTimeout) : TC_ClientSocket(sIp, iPort, iTimeout) { @@ -508,87 +597,130 @@ public: /** * @brief 发送到服务器 + * @brief Send to the Server * @param sSendBuffer 发送buffer + * @param sSendBuffer Send buffer * @param iSendLen 发送buffer的长度 + * @param iSendLen Send buffer length * @return int 0 成功,<0 失败 + * @return int: 0 success, <0 fail */ virtual int send(const char *sSendBuffer, size_t iSendLen); /** * @brief 从服务器返回不超过iRecvLen的字节 + * @brief return Bytes from the server not exceeding iRecvLen * @param sRecvBuffer 接收buffer + * @param sRecvBuffer receive buffer * @param iRecvLen 指定接收多少个字符才返回,输出接收数据的长度 + * @param iRecvLen Specify the number of characters to receive before returning, amd output the length of the received data * @return int 0 成功,<0 失败 + * @return int: 0 success, <0 fail */ virtual int recv(char *sRecvBuffer, size_t &iRecvLen); /** * @brief 从服务器直到结束符(注意必须是服务器返回的结束符, * 而不是中间的符号 ) 只能是同步调用 + * @brief From the server to the ending charactor, can only be a synchronous call + * (note that it must be the ending charactor returned by the server instead of a middle symbol) * @param sRecvBuffer 接收buffer, 包含分隔符 + * @param sRecvBuffer receive buffer, including separators * @param sSep 分隔符 + * @param sSep separator * @return int 0 成功,<0 失败 + * @return int: 0 success, <0 fail */ int recvBySep(string &sRecvBuffer, const string &sSep); /** - * @brief 接收倒服务器关闭连接为止 + * @brief 接收到服务器关闭连接为止 + * @brief Keep receiving until the server connection is closed * @param recvBuffer * * @return int 0 成功,<0 失败 + * @return int: 0 success, <0 fail */ int recvAll(string &sRecvBuffer); /** * @brief 从服务器返回iRecvLen的字节 + * @brief Return the Bytes of iRecvLen from the server * @param sRecvBuffer, sRecvBuffer的buffer长度必须大于等于iRecvLen + * @param sRecvBuffer, its buffer length must be greater than or equal to iRecvLen * @param iRecvLen * @return int 0 成功,<0 失败 + * @return int: 0 success, <0 fail */ int recvLength(char *sRecvBuffer, size_t iRecvLen); /** * @brief 发送到服务器, 从服务器返回不超过iRecvLen的字节 + * @brief Send to the server, return no more than iRecvLen bytes from the server * @param sSendBuffer 发送buffer + * @param sSendBuffer send buffer * @param iSendLen 发送buffer的长度 + * @param iSendLen send buffer length * @param sRecvBuffer 接收buffer + * @param sRecvBuffer receive buffer * @param iRecvLen 接收buffer的长度指针[in/out], * 输入时表示接收buffer的大小,返回时表示接收了多少个字符 + * @param iRecvLen receive the length pointer[in/out] of buffer, + * When inputing, it indicates the size of the received buffer. + * When returning, it indicates how many characters have been received * @return int 0 成功,<0 失败 + * @return int: 0 success, <0 fail */ int sendRecv(const char* sSendBuffer, size_t iSendLen, char *sRecvBuffer, size_t &iRecvLen); /** - * @brief 发送倒服务器, 并等待服务器直到结尾字符, 包含结尾字符 + * @brief 发送到服务器, 并等待服务器直到结尾字符, 包含结尾字符 * sSep必须是服务器返回的结束符,而不是中间的符号,只能是同步调用 * (一次接收一定长度的buffer,如果末尾是sSep则返回, * 否则继续等待接收) + * @brief Send to the server and wait for the server until the ending charactor. + * sSep must be the ending charactor returned by the server, instead of a middle symbol. It can only be called synchronously . + * (Once a certain length of buffer is received, if the end is sSep, then returns, otherwise it will continue to wait for reception). * * @param sSendBuffer 发送buffer + * @param sSendBuffer send buffer * @param iSendLen 发送buffer的长度 + * @param iSendLen send buffer length * @param sRecvBuffer 接收buffer + * @param sRecvBuffer receive buffer * @param sSep 结尾字符 + * @param sSep ending charactor * @return int 0 成功,<0 失败 + * @return int: 0 success, <0 fail */ int sendRecvBySep(const char* sSendBuffer, size_t iSendLen, string &sRecvBuffer, const string &sSep); /** - * @brief 发送倒服务器, 并等待服务器直到结尾字符(\r\n), 包含\r\n + * @brief 发送到服务器, 并等待服务器直到结尾字符(\r\n), 包含\r\n * 注意必须是服务器返回的结束符,而不是中间的符号 * 只能是同步调用 * (一次接收一定长度的buffer,如果末尾是\r\n则返回,否则继续等待接收) + * @brief Send to the server, and wait for the server until ending characters(\r\n), including \r\n + * Attention that the ending character must be returned from the server, instead of a certain symbol in the middle. + * It can only be called synchronously. * * @param sSendBuffer 发送buffer + * @param sSendBuffer send buffer * @param iSendLen 发送buffer的长度 + * @param iSendLen send buffer length * @param sRecvBuffer 接收buffer + * @param sRecvBuffer receive buffer * @param sSep 结尾字符 + * @param sSep ending charactor * @return int 0 成功,<0 失败 + * @return int: 0 success, <0 fail */ int sendRecvLine(const char* sSendBuffer, size_t iSendLen, string &sRecvBuffer); /** * @brief 发送到服务器, 接收直到服务器关闭连接为止 * 此时服务器关闭连接不作为错误 + * @brief send to the server, keep receiving until the server connection is closed. * @param sSendBuffer * @param iSendLen * @param sRecvBuffer @@ -600,6 +732,7 @@ public: protected: /** * @brief 获取socket + * @brief get socket * * @return int */ @@ -609,20 +742,27 @@ protected: /*************************************TC_TCPClient**************************************/ /** * @brief 多线程使用的时候,不用多线程同时send/recv,小心串包 + * @brief When using multithreading, do not send/recv with multithreading at the same time. Be careful about mixing packets. + */ class TC_UDPClient : public TC_ClientSocket { public: /** * @brief 构造函数 + * @brief Constructor */ TC_UDPClient(){}; /** * @brief 构造函数 + * @brief Constructor * @param sIp 服务器IP + * @param sIp server IP * @param iPort 端口 + * @param iPort Port * @param iTimeout 超时时间, 毫秒 + * @param iTimeout Timeout, unit: ms */ TC_UDPClient(const string &sIp, int iPort, int iTimeout) : TC_ClientSocket(sIp, iPort, iTimeout) { @@ -630,59 +770,88 @@ public: /** * @brief 发送数据 + * @brief Send Data * @param sSendBuffer 发送buffer + * @param sSendBuffer send buffer * @param iSendLen 发送buffer的长度 + * @param iSendLen send buffer length * * @return int 0 成功,<0 失败 + * @return int: 0 success, <0 fail */ int send(const char *sSendBuffer, size_t iSendLen); /** * @brief 接收数据 + * @brief receive data * @param sRecvBuffer 接收buffer + * @param sRecvBuffer receive buffer * @param iRecvLen 输入/输出字段 + * @param iRecvLen input/output field * @return int 0 成功,<0 失败 + * @return int: 0 success, <0 fail */ int recv(char *sRecvBuffer, size_t &iRecvLen); /** * @brief 接收数据, 并返回远程的端口和ip + * @brief receive data, and return remote port and IP * @param sRecvBuffer 接收buffer + * @param sRecvBuffer receive buffer * @param iRecvLen 输入/输出字段 + * @param iRecvLen input/output field * @param sRemoteIp 输出字段, 远程的ip + * @param sRemoteIp output field, remote IP * @param iRemotePort 输出字段, 远程端口 + * @param iRemotePort output field, remote port * * @return int 0 成功,<0 失败 + * @return int: 0 success, <0 fail */ int recv(char *sRecvBuffer, size_t &iRecvLen, string &sRemoteIp, uint16_t &iRemotePort); /** * @brief 发送并接收数据 + * @brief Send and Receive Data * @param sSendBuffer 发送buffer + * @param sSendBuffer send buffer * @param iSendLen 发送buffer的长度 + * @param iSendLen send buffer length * @param sRecvBuffer 输入/输出字段 + * @param sRecvBuffer input/output field * @param iRecvLen 输入/输出字段 + * @param iRecvLen input/output field * * @return int 0 成功,<0 失败 + * @return int: 0 success, <0 fail */ int sendRecv(const char *sSendBuffer, size_t iSendLen, char *sRecvBuffer, size_t &iRecvLen); /** * @brief 发送并接收数据, 同时获取远程的ip和端口 + * @brief Send and receive data, and get the remote port and IP at the same time. * @param sSendBuffer 发送buffer + * @param sSendBuffer send buffer * @param iSendLen 发送buffer的长度 + * @param iSendLen send buffer length * @param sRecvBuffer 输入/输出字段 + * @param sRecvBuffer input/output field * @param iRecvLen 输入/输出字段 + * @param iRecvLen input/output field * @param sRemoteIp 输出字段, 远程的ip + * @param sRemoteIp output field, remote IP * @param iRemotePort 输出字段, 远程端口 + * @param iRemotePort output field, remote port * * @return int 0 成功,<0 失败 + * @return int: 0 success, <0 fail */ int sendRecv(const char *sSendBuffer, size_t iSendLen, char *sRecvBuffer, size_t &iRecvLen, string &sRemoteIp, uint16_t &iRemotePort); protected: /** * @brief 获取socket + * @brief Get Socket * * @return TC_Socket& */ diff --git a/util/include/util/tc_common.h b/util/include/util/tc_common.h index f7ba44887be26932ae686151e91bcb533255abd5..38b41a8d89c157fb69fbd1496a7193b272a3430c 100644 --- a/util/include/util/tc_common.h +++ b/util/include/util/tc_common.h @@ -47,22 +47,28 @@ namespace tars /** * @file tc_common.h * @brief 帮助类,都是静态函数,提供一些常用的函数 . +* @brief Helper Class. There're all static functions in this which provides some commonly used functions * */ ///////////////////////////////////////////////// - /** - * @brief 基础工具类,提供了一些非常基本的函数使用. - * - * 这些函数都是以静态函数提供。 包括以下几种函数: - * - * Trim类函数,大小写转换函数,分隔字符串函数(直接分隔字符串, - * - * 数字等),时间相关函数,字符串转换函数,二进制字符串互转函数, - * - * 替换字符串函数,Ip匹配函数,判断一个数是否是素数等 - */ -class TC_Common +/** +* @brief 基础工具类,提供了一些非常基本的函数使用. +* @brief Basic Utility Class. Some basic functions are provided. +* +* 这些函数都是以静态函数提供。 包括以下几种函数: +* These functions are provided as static functions.It includes the following functions: +* +* Trim类函数,大小写转换函数,分隔字符串函数(直接分隔字符串, +* Trim class functions, case conversion functions, delimited string functions (directly delimited strings, numbers, etc.), +* +* 数字等),时间相关函数,字符串转换函数,二进制字符串互转函数, +* time-dependent functions, string conversion functions, binary string conversion functions, +* +* 替换字符串函数,Ip匹配函数,判断一个数是否是素数等 +* replacement string functions, IP matching functions, determining whether a number is a prime number, etc. +*/ +class UTIL_DLL_API TC_Common { public: @@ -71,12 +77,14 @@ public: /** * @brief 跨平台sleep + * @brief Cross Platform Sleep */ static void sleep(uint32_t sec); static void msleep(uint32_t ms); /** * @brief 浮点数比较,double 默认取6位精度,float默认6位精度 + * @brief Floating Number Comparison, double defaults to be 6-bit precision, and float defaults to be 6-bit precision as well. */ static bool equal(double x, double y, double epsilon = _EPSILON_DOUBLE); static bool equal(double x, double y, float epsilon ); @@ -86,6 +94,7 @@ public: /** * @brief vector double 各种场景比较函数 + * @brief vector double, comparison functions for various scenarios */ static bool equal(const vector & vx, const vector& vy, double epsilon = _EPSILON_DOUBLE); static bool equal(const vector& vx, const vector& vy, float epsilon ); @@ -94,6 +103,7 @@ public: /** * @brief map中如果key或者value为double/float字段,则用此模板函数比较 + * @brief In map, if the key or value is the double/float field, use this template function to compare. */ template static bool equal(const V& x, const V& y, E eps); @@ -102,6 +112,7 @@ public: /** * 固定宽度填充字符串, 用于输出对齐格式用(默认右填充) + * Fixed width filled string for output alignment format (default right-padding) * @param s * @param c * @param n @@ -120,232 +131,327 @@ public: /** * @brief 去掉头部以及尾部的字符或字符串. + * @brief Remove the head and the tail characters or strings * * @param sStr 输入字符串 + * @param sStr input string * @param s 需要去掉的字符 + * @param s the characters which need to be removed * @param bChar 如果为true, 则去掉s中每个字符; 如果为false, 则去掉s字符串 + * @param bChar bool : true, Remove each character in 's'; false, remove the s String * @return string 返回去掉后的字符串 + * @return string Return the removed string */ static string trim(const string &sStr, const string &s = " \r\n\t", bool bChar = true); /** * @brief 去掉左边的字符或字符串. + * @brief Remove left character or string * * @param sStr 输入字符串 + * @param sStr input string * @param s 需要去掉的字符 + * @param s the characters which need to be removed * @param bChar 如果为true, 则去掉s中每个字符; 如果为false, 则去掉s字符串 + * @param bChar bool : true, Remove each character in 's'; false, remove the s String * @return string 返回去掉后的字符串 + * @return string Return the removed string */ static string trimleft(const string &sStr, const string &s = " \r\n\t", bool bChar = true); /** * @brief 去掉右边的字符或字符串. + * @brief Remove right character or string * * @param sStr 输入字符串 + * @param sStr input string * @param s 需要去掉的字符 + * @param s the characters which need to be removed * @param bChar 如果为true, 则去掉s中每个字符; 如果为false, 则去掉s字符串 + * @param bChar bool : true, Remove each character in 's'; false, remove the s String * @return string 返回去掉后的字符串 + * @return string Return the removed string */ static string trimright(const string &sStr, const string &s = " \r\n\t", bool bChar = true); /** * @brief 字符串转换成小写. + * @brief Convert string to lowercase. * * @param sString 字符串 + * @param sString String * @return string 转换后的字符串 + * @return string the converted string */ static string lower(const string &sString); /** * @brief 字符串转换成大写. + * @brief Convert string to uppercase. * * @param sString 字符串 + * @param sString string * @return string 转换后的大写的字符串 + * @return string the converted string */ static string upper(const string &sString); /** * @brief 字符串是否都是数字的. + * @brief Whether strings are all numbers or not. * * @param sString 字符串 + * @param sString string * @return bool 是否是数字 + * @return bool whether number or not */ static bool isdigit(const string &sInput); /** * @brief 字符串转换成时间结构. + * @brief Convert string to time structure. * * @param sString 字符串时间格式 + * @param sString string Time Format * @param sFormat 格式 + * @param sFormat format * @param stTm 时间结构 + * @param stTm time structure * @return 0: 成功, -1:失败 + * @return 0: success, -1: fail */ static int str2tm(const string &sString, const string &sFormat, struct tm &stTm); /** * @brief GMT格式的时间转化为时间结构 + * @brief Conversion of time into time structure in GMT format * * eg.Sat, 06 Feb 2010 09:29:29 GMT, %a, %d %b %Y %H:%M:%S GMT * * 可以用mktime换成time_t, 但是注意时区 可以用mktime(&stTm) + * You can replace time_t with mktime. Be careful about the time zones, and it can be used with mktime (&stTm) * * - timezone换成本地的秒(time(NULL)值相同) timezone是系统的 , + * - timezone changes costs to local seconds (time (NULL) values are the same). Timezones is systematic. * * 需要extern long timezone; + * need extern long timezone; * * @param sString GMT格式的时间 + * @param sString time in GMT format * @param stTm 转换后的时间结构 + * @param stTm converted Time Structure * @return 0: 成功, -1:失败 + * @return 0: success, -1: fail */ static int strgmt2tm(const string &sString, struct tm &stTm); /** * @brief 格式化的字符串时间转为时间戳. + * @brief Format time string to timestamp * * @param sString 格式化的字符串时间 + * @param sString format time string * @param sFormat 格式化的字符串时间的格式,默认为紧凑格式 + * @param sFormat format of formatted string time * @return time_t 转换后的时间戳 + * @return time_t the converted timestamp */ static time_t str2time(const string &sString, const string &sFormat = "%Y%m%d%H%M%S"); /** * @brief 时间转换成字符串. + * @brief Convert time into string. * * @param stTm 时间结构 + * @param stTm time structure * @param sFormat 需要转换的目标格式,默认为紧凑格式 + * @param sFormat Target format to be converted, default to compact format * @return string 转换后的时间字符串 + * @return string converted time string */ static string tm2str(const struct tm &stTm, const string &sFormat = "%Y%m%d%H%M%S"); /** * @brief 时间转换成字符串. + * @brief Convert time into string * * @param t 时间结构 + * @param t time structure * @param sFormat 需要转换的目标格式,默认为紧凑格式 + * @param sFormat Target format to be converted, default to compact format * @return string 转换后的时间字符串 + * @return string converted time string */ static string tm2str(const time_t &t, const string &sFormat = "%Y%m%d%H%M%S"); /** * @brief 时间转换tm. + * @brief Convert time into tm. * * @param t 时间结构 + * @param t time structure */ static void tm2time(const time_t &t, struct tm &tt); /** * @brief time_t转换成tm(不用系统的localtime_r, 否则很慢!!!) + * @brief Convert time_t to tm (Don't use system's localtime_r. The function will be slowed down.) * * @param t 时间结构 + * @param t time structure * @param sFormat 需要转换的目标格式,默认为紧凑格式 + * @param sFormat Target format to be converted, default to compact format * @return string 转换后的时间字符串 + * @return string converted time string */ static void tm2tm(const time_t &t, struct tm &stTm); /** * @brief 获取当前的秒和毫秒 + * @brief Get the current seconds and milliseconds * * @param t 时间结构 + * @param t time structure */ static int gettimeofday(struct timeval &tv); /** * @brief 当前时间转换成紧凑格式字符串 + * @brief Convert current time to compact string * @param sFormat 格式,默认为紧凑格式 + * @param sFormat the format, default to compact format * @return string 转换后的时间字符串 + * @return string converted time string */ static string now2str(const string &sFormat = "%Y%m%d%H%M%S"); /** * @brief 时间转换成GMT字符串,GMT格式:Fri, 12 Jan 2001 18:18:18 GMT + * @brief Convert time into GMT string, GMT格式:Fri, 12 Jan 2001 18:18:18 GMT * @param stTm 时间结构 + * @param stTm time structure * @return string GMT格式的时间字符串 + * @return string time string in GMT format */ static string tm2GMTstr(const struct tm &stTm); /** * @brief 时间转换成GMT字符串,GMT格式:Fri, 12 Jan 2001 18:18:18 GMT + * @brief Convert time into GMT string, GMT格式:Fri, 12 Jan 2001 18:18:18 GMT * @param stTm 时间结构 + * @param stTm time structure * @return string GMT格式的时间字符串 + * @return string time string in GMT format */ static string tm2GMTstr(const time_t &t); /** * @brief 当前时间转换成GMT字符串,GMT格式:Fri, 12 Jan 2001 18:18:18 GMT + * @brief Convert current time into GMT string, GMT格式:Fri, 12 Jan 2001 18:18:18 GMT * @return string GMT格式的时间字符串 + * @return string time string in GMT format */ static string now2GMTstr(); /** * @brief 当前的日期(年月日)转换成字符串(%Y%m%d). + * @brief Get current date(yearmonthday) and convert it into string (%Y%m%d). * * @return string (%Y%m%d)格式的时间字符串 + * @return string time string in (%Y%m%d) format */ static string nowdate2str(); /** * @brief 当前的时间(时分秒)转换成字符串(%H%M%S). + * @brief Get current time(hourminutesecond) and convert it into string (%H%M%S). * * @return string (%H%M%S)格式的时间字符串 + * @return string time string in (%H%M%S) format */ static string nowtime2str(); /** * @brief 获取当前时间的的毫秒数. + * @brief Get the value of milliseconds of current time. * * @return int64_t 当前时间的的毫秒数 + * @return int64_t current milliseconds of this time */ static int64_t now2ms(); /** * @brief 取出当前时间的微秒. + * @brief Take out microseconds of current time. * * @return int64_t 取出当前时间的微秒 + * @return int64_t Take out microseconds of current time. */ static int64_t now2us(); /** * @brief 字符串转化成T型,如果T是数值类型, 如果str为空,则T为0. + * @brief Convert string to type T. if T is a numeric type and STR is empty, then T values 0. * * @param sStr 要转换的字符串 + * @param sStr the string needs to be converted * @return T T型类型 + * @return T the type of type T */ template static T strto(const string &sStr); /** * @brief 字符串转化成T型. + * @brief Convert string to type T * * @param sStr 要转换的字符串 + * @param sStr the string needs to be converted * @param sDefault 缺省值 + * @param sDefault default value * @return T 转换后的T类型 + * @return T the converted type of type T */ template static T strto(const string &sStr, const string &sDefault); /** * @brief 解析字符串,用分隔符号分隔,保存在vector里 - * + * @brief Parse string, separate with separator, and save in vector + * * 例子: |a|b||c| - * + * Example: |a|b||c| + * * 如果withEmpty=true时, 采用|分隔为:"","a", "b", "", "c", "" + * If 'withEmpty=true' then use '|' to separate it into "","a", "b", "", "c", "". * * 如果withEmpty=false时, 采用|分隔为:"a", "b", "c" + * If 'withEmpty=false' then use '|' to separate it into "a", "b", "c". * * 如果T类型为int等数值类型, 则分隔的字符串为"", 则强制转化为0 + * If the T type is a numeric type such as int, the delimited string is' ', then it is forced to 0. * * @param sStr 输入字符串 + * @param sStr input string * @param sSep 分隔字符串(每个字符都算为分隔符) + * @param sSep the separator string (each character counts as a separator) * @param withEmpty true代表空的也算一个元素, false时空的过滤 + * @param withEmpty bool: true, represented that empty is also an element ; false, filter empty ones. * @return 解析后的字符vector + * @return parsed character: vector */ template static vector sepstr(const string &sStr, const string &sSep, bool withEmpty = false); /** * @brief T型转换成字符串,只要T能够使用ostream对象用<<重载,即可以被该函数支持 + * @brief Convert T-type to string. As long as T can use ostream object with << to overload, it can be supported by this function. + * * @param t 要转换的数据 + * @param t the data needs to be converted * @return 转换后的字符串 + * @return the converted string */ template inline static string tostr(const T &t) @@ -357,142 +463,203 @@ public: /** * @brief vector转换成string. + * @brief Convert vector to string. * * @param t 要转换的vector型的数据 + * @param t data which need to be convertes to vector type * @return 转换后的字符串 + * @return the converted string */ template static string tostr(const vector &t); /** * @brief 把map输出为字符串. + * @brief export map as string * * @param map 要转换的map对象 + * @param map the map object needs to be converted * @return string 输出的字符串 + * @return output string */ template static string tostr(const map &t); /** * @brief map输出为字符串. + * @brief export map as string * * @param multimap map对象 + * @param multimap the map object needs to be converted * @return 输出的字符串 + * @return output string */ template static string tostr(const multimap &t); /** * @brief 把map输出为字符串. + * @brief export map as string * * @param map 要转换的map对象 + * @param map the map object needs to be converted * @return string 输出的字符串 + * @return output string */ template static string tostr(const unordered_map &t); /** * @brief pair 转化为字符串,保证map等关系容器可以直接用tostr来输出 + * @brief Convert pair to string, ensure that the relationship containers such as map can output directly with tostr. * @param pair pair对象 + * @param pair object pair * @return 输出的字符串 + * @return output string */ template static string tostr(const pair &itPair); /** * @brief container 转换成字符串. + * @brief Convert container to string * * @param iFirst 迭代器 + * @param iFirst iterator * @param iLast 迭代器 + * @param iLast iterator * @param sSep 两个元素之间的分隔符 + * @param sSep the separator between two elements * @return 转换后的字符串 + * @return the converted string */ template static string tostr(InputIter iFirst, InputIter iLast, const string &sSep = "|"); /** * @brief 二进制数据转换成字符串. + * @brief Convert binary data t0 string * * @param buf 二进制buffer + * @param buf binary buffer * @param len buffer长度 + * @param len buffer length * @param sSep 分隔符 + * @param sSep separator * @param lines 多少个字节换一行, 默认0表示不换行 + * @param lines The max number of bytes for oneline.By default, 0 means no new line. * @return 转换后的字符串 + * @return the converted string */ static string bin2str(const void *buf, size_t len, const string &sSep = "", size_t lines = 0); /** * @brief 二进制数据转换成字符串. + * @brief Convert binary data t0 string * * @param sBinData 二进制数据 + * @param sBinData binary data * @param sSep 分隔符 + * @param sSep separator * @param lines 多少个字节换一行, 默认0表示不换行 + * @param lines The max number of bytes for oneline.By default, 0 means no new line. * @return 转换后的字符串 + * @return the converted string */ static string bin2str(const string &sBinData, const string &sSep = "", size_t lines = 0); /** * @brief 字符串转换成二进制. + * @brief Convert string to binary * * @param psAsciiData 字符串 + * @param psAsciiData string * @param sBinData 二进制数据 + * @param sBinData binary data * @param iBinSize 需要转换的字符串长度 + * @param iBinSize the length of the string which needs to be converted. * @return 转换长度,小于等于0则表示失败 + * @return Conversion length, less than or equal to 0 means failure */ static int str2bin(const char *psAsciiData, unsigned char *sBinData, int iBinSize); /** * @brief 字符串转换成二进制. + * @brief convert string to binary * * @param sBinData 要转换的字符串 + * @param sBinData the string needs to be converted * @param sSep 分隔符 + * @param sSep separator * @param lines 多少个字节换一行, 默认0表示不换行 + * @param lines The max number of bytes for oneline.By default, 0 means no new line. * @return 转换后的二进制数据 + * @return the converted binary data */ static string str2bin(const string &sBinData, const string &sSep = "", size_t lines = 0); /** * @brief 替换字符串. + * @brief replace string * * @param sString 输入字符串 + * @param sString input string * @param sSrc 原字符串 + * @param sSrc the original string * @param sDest 目的字符串 + * @param sDest the target string * @return string 替换后的字符串 + * @return string the converted string */ static string replace(const string &sString, const string &sSrc, const string &sDest); /** * @brief 批量替换字符串. + * @brief Batch replace string. * * @param sString 输入字符串 + * @param sString input string * @param mSrcDest map<原字符串,目的字符串> + * @param mSrcDest map * @return string 替换后的字符串 + * @return string the converted string */ static string replace(const string &sString, const map& mSrcDest); /** * @brief 匹配以.分隔的字符串,pat中*则代表通配符,代表非空的任何字符串 * s为空, 返回false ,pat为空, 返回true + * @brief Match string separated by '.' And '*' in pat represents wildcard which represents any string that is not empty. + * If s is empty, return false. If pat is empty, return true. * @param s 普通字符串 + * @param s normal string * @param pat 带*则被匹配的字符串,用来匹配ip地址 + * @param pat string matched with * to match IP address * @return 是否匹配成功 + * @return whether they matches or not */ static bool matchPeriod(const string& s, const string& pat); /** * @brief 匹配以.分隔的字符串. + * @brief Match strings separated by '.' * * @param s 普通字符串 + * @param s normal string * @param pat vector中的每个元素都是带*则被匹配的字符串,用来匹配ip地址 + * @param pat each elment in this vector means string matched with * to match IP address * @return 是否匹配成功 + * @return whether they matches or not */ static bool matchPeriod(const string& s, const vector& pat); /** * @brief 判断一个数是否为素数. - * + * @brief Determine whether a number is prime or not * @param n 需要被判断的数据 + * @param n the data needs to be determined * @return true代表是素数,false表示非素数 + * @return true for prime , false for non prime */ static bool isPrimeNumber(size_t n); @@ -505,13 +672,17 @@ public: /** * @brief 忽略管道异常 + * @brief Ignore pipe exceptions */ static void ignorePipe(); /** * @brief 生成基于16进制字符的随机串 + * @brief Generating random strings based on hexadecimal characters. * @param p 存储随机字符串 + * @param p store random string * @param len 字符串大小 + * @param len string length */ static void getRandomHexChars(char* p, unsigned int len); @@ -519,23 +690,32 @@ public: /** * @brief 将一个string类型转成一个字节 . + * @brief Convert a string type to a byte . * * @param sWhat 要转换的字符串 + * @param sWhat the string which needs to be converted * @return char 转换后的字节 + * @return char the converted byte */ static char x2c(const string &sWhat); /** * @brief 大小字符串换成字节数,支持K, M, G两种 例如: 1K, 3M, 4G, 4.5M, 2.3G + * @brief The string can be changed into bytes. It supports two kinds of K, M and G, such as 1K, 3M, 4G, 4.5M and 2.3G * @param s 要转换的字符串 + * @param s the string which needs to be converted * @param iDefaultSize 格式错误时, 缺省的大小 + * @param iDefaultSize the default size in case of format error * @return 字节数 + * @return Bytes */ static size_t toSize(const string &s, size_t iDefaultSize); /** * @brief 获取主机名称. + * @brief Get machine name * @return string 主机名,失败是返回空 + * @return string machine name. if failed returns null */ static string getHostName(); @@ -577,6 +757,19 @@ namespace p } }; + template<> + struct strto1 + { + unsigned char operator()(const string &sStr) + { + if(!sStr.empty()) + { + return (unsigned char)sStr[0]; + } + return 0; + } + }; + template<> struct strto1 { diff --git a/util/include/util/tc_config.h b/util/include/util/tc_config.h index 532570161aeaaa6b7a96ee76a911ca814f367fb4..1c9f5aa66b93918beedf19c2485be47c3a77f30e 100644 --- a/util/include/util/tc_config.h +++ b/util/include/util/tc_config.h @@ -28,27 +28,32 @@ namespace tars ///////////////////////////////////////////////// /** * @file tc_config.h - * @brief 配置文件读取类. + * @brief 配置文件读取类. + * @brief Config File Reading Class */ ///////////////////////////////////////////////// /** * 域分隔符 +* Field Separator */ const char TC_CONFIG_DOMAIN_SEP = '/'; /** * 参数开始符 +* Parameter Start Character */ const char TC_CONFIG_PARAM_BEGIN = '<'; /** * 参数结束符 +* Parameter Ender Character */ const char TC_CONFIG_PARAM_END = '>'; /** * @brief 配置文件异常类. +* @brief Config File Exception Class */ struct TC_Config_Exception : public TC_Exception { @@ -59,6 +64,7 @@ struct TC_Config_Exception : public TC_Exception /** * @brief 配置没有文件错误 + * @brief No Config File Error */ struct TC_ConfigNoParam_Exception : public TC_Exception { @@ -69,6 +75,7 @@ struct TC_ConfigNoParam_Exception : public TC_Exception /** * @brief 定义配置文件中的域的类. +* @brief Class that defines the domain in the configuration file */ class TC_ConfigDomain { @@ -77,27 +84,34 @@ public: /** * @brief 构造函数. + * @brief Constructor * * @param sLine 指配置文件中的一行,按行读取 + * @param sLine Refers to a line in the configuration file, read by line */ TC_ConfigDomain(const string &sLine); /** * @brief 析够函数. + * @brief Destructor */ ~TC_ConfigDomain(); /** * @brief 拷贝复制. + * @brief Copy * * @param tcd 一个TC_ConfigDomain对象,指配置文件的一个域 + * @param tcd a TC_ConfigDomain object, refers to a domain of the configuration file */ TC_ConfigDomain(const TC_ConfigDomain &tcd); /** * @brief 赋值. + * @brief Assignment * * @param tcd 一个TC_ConfigDomain对象,指配置文件的一个域 + * @param tcd a TC_ConfigDomain object, refers to a domain of the configuration file */ TC_ConfigDomain& operator=(const TC_ConfigDomain &tcd); @@ -110,50 +124,74 @@ public: /** * @brief 解析一个domain + * @brief Parse a domain * 对形如"/Main/Domain"的path进行解析,解析的结果为一个 * DomainPath 类型,包括路径_domains和路径中对应的配置项_param. - * + * + * Parsing a path like'/Main/Domain'results in a DomainPath type, + * including the path'_domains' and the corresponding configuration item in the path '_param' + * * @param path 一个经过处理的字符串,必须符合一定的要求 + * @param path A processed string must meet certain requirements * @param bWithParam "/Main/Domain"时bWithParam为ture * "/Main/Domain"时bWithParam为false + * @param bWithParam bool: true, when'/Main/Domain'; + * false, when'/Main/Domain' * @return DomainPath 一个DomainPath对象,解析出域中的域名和参数 + * @return DomainPath A DomainPath object that resolves domain names and parameters in a domain */ static DomainPath parseDomainName(const string& path, bool bWithParam); /** * @brief 增加子域名称 + * @brief Add Subdomain Name * 增加一个子域,name是子域的名字,比如"/Main/Domain" * 再增加一个name为subDomain的子域,变成"/Main/Domain/subDomain" + * Add a subdomain, and 'name' is its name, such as "/Main/Domain" + * Add an other subdomain which named 'subDomain', such as "/Main/Domain/subDomain" + * * * @param name 子域的名称 + * @param name subdomain name * @return TC_ConfigDomain* 指向子域的指针 + * @return TC_ConfigDomain* the pointer which points to the subdomain * @throws TC_Config_Exception */ TC_ConfigDomain* addSubDomain(const string& name); /** * @brief 递归搜索子域 Sub Domain. + * @brief Recursive search subdomain Sub Domain. * * @param itBegin 迭代器 ,指向_domains的顶部 + * @param itBegin iterator, point to the button of the _domain * @param itEnd 迭代器 ,指向_domains的底部 + * @param itBegin iterator, point to the button of the _domain * @return TC_ConfigDomain* 指向目标子域的指针 + * @return TC_ConfigDomain* a point point to the target subdomain */ TC_ConfigDomain *getSubTcConfigDomain(vector::const_iterator itBegin, vector::const_iterator itEnd); const TC_ConfigDomain *getSubTcConfigDomain(vector::const_iterator itBegin, vector::const_iterator itEnd) const; /** * @brief Get Param Value 获取参数/值对. + * @brief Get Param Value Get parameter/value pairs. * * @param sName 配置项名称 + * @param sName Configuration Item Name * @return 配置项对应的值 + * @return the value of the configration item */ string getParamValue(const string &sName) const; /** - * @brief Get Param Map 获取map + * @brief Get Param Map 获取map * map是参数/值对,是配置项和配置项的值对应的键值对, * eg. SyncThreadNum = 2 + * Map is a parameter/value pair, a key-value pair corresponding to the value of the configuration item and the configuration item, + * eg. SyncThreadNum = 2 * @return 一个域中的参数和其对应的值的map + * @return a map of parameters and their corresponding values in a domain */ const map& getParamMap() const { return _param; } @@ -168,12 +206,14 @@ public: * @brief Set Param Value 设置参数/值对. * * @param sLine 行 + * @param sLine line * @return */ void setParamValue(const string &sLine); /** * @brief 插入参数,把key里没有的配置项添加到最后 + * @brief Insert a parameter to add a configuration item that is not in the key to the last * * @param 存配置项和对应配置项值的map */ @@ -183,53 +223,68 @@ public: * @brief Destroy 释放. * * @return 无 + * @return void */ void destroy(); /** * @brief Get Name 获取域名称 + * @brief Get Name Get Domain Name * @return 域名称 + * @return the domain name */ string getName() const; /** * @brief 设置域名称 + * @brief Set Domain Name * * @param 域名称 + * @param name domain name */ void setName(const string& name); /** * @brief 按照文件中的顺序获取key + * @brief Get keys in the order they appear in the file * * @return vector存放key的vector + * @return the vector which stores keys in vector */ vector getKey() const; /** * @brief 按照文件中的顺序获取line + * @brief Get 'line' in the order they appear in the file * * @return vector存放key的vector + * @return the vector which stores keys in vector */ vector getLine() const; /** * @brief 按照文件中的顺序获取子Domain + * @brief Get subdomains in the order they appear in the file * * @return vector存放域名字的vector + * @return the vector which stores keys in vector */ vector getSubDomain() const; /** * @brief 转换成配置文件的字符串格式. + * @brief Convert to the string format of the configuration file. * * @param i tab的层数 + * @param i number of layers of 'tab' * @return string类型配置字符串 + * @return string type configuration string */ string tostr(int i) const; /** * @brief 克隆. + * @brief Clone. * * @return TC_ConfigDomain* */ @@ -240,6 +295,7 @@ public: /** * @brief 转义. + * @brief Escape. * * @param name * @return string @@ -248,6 +304,7 @@ public: /** * @brief 方向转义. + * @brief Direction escaping * * @param s * @return string @@ -256,10 +313,14 @@ public: /** * @brief 设置参数/值对 + * @brief Set param/key pairs * * @param sName 配置项名称 + * @param sName the name of the configuration item * @param sValue 配置项的值 + * @param sValue the value of the configuration item * @return 无 + * @return void */ void setParamValue(const string &sName, const string &sValue); @@ -267,51 +328,66 @@ protected: /** * 域名称 + * Domain Name */ string _name; /** * name/value对,配置项的名称和配置项的值 + * name/value pair, the name and value of the configuration item */ map _param; /** * key也就是配置项的插入顺序 + * key, the insertion order of configuration items */ vector _key; /** * 子域 + * Subdomain */ map _subdomain; /** * 域的插入顺序 + * the insertion order of the domain */ vector _domain; /** * 整行的配置列表 + * Configuration list for the whole row */ vector _line; }; /** * @brief 定义配置文件的类(兼容wbl模式). + * @brief Define the class of the profile (compatible with WBL mode). * 支持从string中解析配置文件; + * Support parsing configuration files from strings; * 支持生成配置文件; + * Support the generation of configuration files; * 解析出错抛出异常; + * Parse error and throw exception; + * 采用[]获取配置,如果无配置则抛出异常; + * Use [] to get the configuration and throw an exception if there is no configuration; * 采用get获取配置,不存在则返回空; + * Use 'get' to get the configuration, and return null if it doesn't exist * 读取配置文件是线程安全的,insert域等函数非线程安全; + * Reading configuration files is thread-safe, functions such as insert fields are not thread-safe; * 例如: + * For example: *
* @@ -323,8 +399,11 @@ protected: *
* 获取参数:conf["/Main/Domain"] 获取域Map: - * getDomainMap("/Main/Domain", m); m得到Name/Value对 + * Get parameter: conf ["/Main/Domain"] Get domain Map: + * getDomainMap("/Main/Domain", m); m得到Name/Value对 + * getDomainMap("/Main/Domain", m); 'm' can get the Name/Value pair * 获取域Vector: getDomainVector("/Main", v); v得到Domain列表 可以增加域或域下面的值对 + * Get Domain Vector: getDomainVector ('/Main', v); 'v' can get a list of Domains to increase the number of the value pairs under the domain or domain */ class TC_Config @@ -333,11 +412,13 @@ public: /** * @brief 构造函数 + * @brief Constructor */ TC_Config(); /** * @brief 拷贝复制. + * @brief Copy * * @param tc为TC_Config类型 */ @@ -345,6 +426,7 @@ public: /** * @brief 赋值. + * @brief Assignment * * @param tcd * @return TC_Config& @@ -353,18 +435,24 @@ public: /** * @brief 解析文件. + * @brief Parse the file. * * 把fileName对应的文件转化为输入流后调用parse对其进行解析 + * Convert the file corresponding to fileName into an input stream and call parse to parse it. * @param sFileName : 文件名称 + * @param sFileName file name * @return 无 + * @return void * @throws TC_Config_Exception */ void parseFile(const string& sFileName); /** - * @brief 解析字符串. + * @brief 解析字符串. + * @brief Parse string * * 把string 类型先转化为输入流后调用parse对其进行解析 + * Convert string type to input stream and call parse to parse it * @return void * @throws TC_Config_Exception */ @@ -373,8 +461,12 @@ public: /** * @brief 获取值, 如果没有则抛出异常, * 对于型如/Main/Domain的字符串,获取域/Main/Domain下的配置项名字为Param的值 + * @brief Get value. + * If no exception is thrown, for strings of which type like /Main/Domain, get the value of the configuration item named 'Param' under the domain '/Main/Domain' * @param sName 参数名称,例如: /Main/Domain - * @return 配置项对应的值 + * @param sName param name, like: /Main/Domain + * @return 配置项对应的值 + * @return the value of the configuration file * @throws TC_Config_Exception */ string operator[](const string &sName) const; @@ -382,82 +474,119 @@ public: /** * @brief 获取值, 注意如果没有不抛出异常,返回空字符串. * 对于型如/Main/Domain的字符串,获取域/Main/Domain下的配置项名字为Param的值 + * @brief Get value. Note that if no exception is thrown, an empty string is returned. + * For strings of type like'/main/domain', get the value of the configuration item named 'Param' under the domain '/Main/Domain' * @param sName 参数名称, 例如: /Main/Domain + * @param sName param name, like: /Main/Domain * @return 配置项对应的值 + * @return the value of the configuration file */ string get(const string &sName, const string &sDefault="") const; /** - * @brief 设置值. + * @brief 设置值. + * @brief Set Value * @param sName 参数名称, 例如: /Main/Domain + * @param sName param name, like: /Main/Domain */ void set(const string &sName, const string &value); /** * @brief GetDomainParamMap获取域下面的参数值对. + * @brief GetDomainParamMap Get the parameter-value pair under the domain + * * @param path 域名称, 域标识, 例如: /Main/Domain + * @param path domain name, domain identifier, such as: '/Main/Domain' * @param m map类型,域内的map列表 + * @param m map type, the map list in the domain * @return bool, 返回域下面的参数值对 + * @return bool, return the parameter-value pair under the domain */ bool getDomainMap(const string &path, map &m) const; /** * @brief 获取域下面的参数值对,不存则返回空map. + * @brief Get the parameter value pair under the domain. If it is not saved, an empty map will be returned. * * @param path 域名称, 域标识, 例如: /Main/Domain + * @param path domain name, domain identifier, such as: '/Main/Domain' * @return map,对应域下面的所有参数值对 + * @return bool, return the parameter-value pair under the domain */ map getDomainMap(const string &path) const; /** - * @brief 获取域下面的所有key, 按照文件的行顺序返回 + * @brief 获取域下面的所有key, 按照文件的行顺序返回 + * @brief Get all the keys under the domain and return them in line order * @param path 域名称, 域标识, 例如: /Main/Domain + * @param path domain name, domain identifier, such as: '/Main/Domain' * @return vector,某个标识下的所有key + * @return vector,All keys under a certain ID */ vector getDomainKey(const string &path) const; /** * @brief 获取域下面的所有非域行, 按照文件的行顺序返回 * 区别于getDomainKey只能获取到key,该接口对带"="的配置也整行返回 + * @brief Get all non domain lines under the domain, and return them in line order of the file + * The difference is that this interface getDomainKey, which can only get the key, also returns the whole line for the configuration with "=". * @param path 域名称, 域标识, 例如: /Main/Domain + * @param path domain name, domain identifier, such as: '/Main/Domain' * @return vector,某个标识下的所有非域行 + * @return vector,All non domain lines under a certain ID */ vector getDomainLine(const string &path) const; /** * @brief getDomainMap 获取域下面的子域. + * * * @param path 域名称, 域标识, 例如: /Main/Domain - * @param v 要获取的子域名字 - * @param vector域下面的域名称 + * @param path domain name, domain identifier, such as: '/Main/Domain' + * @param v 要获取的子域名字, vector下的域名 + * @param v the target subdomian name,the domain name under vector * @return 成功获取返回true,否则返回false + * @return bool: true, successful , false, failed */ bool getDomainVector(const string &path, vector &v) const; /** * @brief 获取域下面的子域, * 不存在则返回空vector按照在文件中的顺序返回 + * @brief Get the subdomain under the domain * @param path 域名称, 域标识, 例如: /Main/Domain + * @param path domain name, domain identifier, such as: '/Main/Domain' * @return vector目标域下面的子域 + * @return vector the subdomain under the target domain */ vector getDomainVector(const string &path) const; /** * @brief 是否存在域. + * @brief Whether the domain exists or not. * * @param path 域名称, 域标识, 例如: /Main/Domain + * @param path domain name, domain identifier, such as: '/Main/Domain' * @return 存在返回true,否则返回false + * @return If the domain does exist, return true, else return false. */ bool hasDomainVector(const string &path) const; /** * @brief 增加域,在当前域下面增加域, 如果已经存在sAddDomain域, * 则认为成功 + * @brief + +Add domain. Add a domain under the current domain. If the sadddomain domain already exists, it is considered to be successful. * @param sCurDomain 域标识符, 例如:/Main/Domain + * @param sCurDomain domain identifier, such as: '/Main/Domain' * @param sAddDomain 需要增加的域名称: 例如: sCurDomain + * @param sAddDomain the name of the domain which need to be added: like: sCurDomain * @param bCreate sCurDomain域不存在的情况下, 是否自动创建 + * @param bCreate When the domain sCurDomain does not exist, determine wheter it needs to be created automatically. * @return 0-成功增加, 1-sCurDomain不存在 + * @return 0 - add successfull, 1 - sCurDomain doesn't exist. */ int insertDomain(const string &sCurDomain, const string &sAddDomain, bool bCreate); @@ -465,25 +594,34 @@ public: /** * @brief 增加参数,即配置项,当前域下面增加配置项参数, * 如果已经有相关参数, 则忽略(不替换) + * @brief Add parameter, i.e. configuration item. Add configuration item parameter under the current domain. If there are already related parameters, ignore (do not replace). * @param sCurDomain 域标识符, 例如:/Main/Domain + * @param sCurDomain domain identifier, such as: '/Main/Domain' * @param m map类型,存参数值对 + * @param m map type, save parameter-value pairs * @param bCreate sCurDomain域不存在的情况下, 是否自动创建 + * @param bCreate When the domain sCurDomain does not exist, determine wheter it needs to be created automatically. * @return 0: 成功, 1:sCurDomain不存在 + * @return 0 - add successfull, 1 - sCurDomain doesn't exist. */ int insertDomainParam(const string &sCurDomain, const map &m, bool bCreate); /** * @brief 合并配置文件到当前配置文件. + * @brief Merge profile to current profile * * @param cf * @param bUpdate true-冲突项更新本配置, false-冲突项不更新 + * @param bUpdate true - update the conflict item to this configuration, false - don't update the conflict item */ void joinConfig(const TC_Config &cf, bool bUpdate); /** * @brief 转换成配置文件的字符串格式. + * @brief convert to the string format of the configuration file * * @return 配置字符串 + * @return the configuration string */ string tostr() const; @@ -491,7 +629,10 @@ protected: /** * @brief Parse输入流, * 最终把输入流解析成为一个TC_ConfigDomain装入stack中 + * @brief Parse Input Stream + * Finally, the input stream is parsed into a TC_ ConfigDomain and is loaded into the stack. * @param 要解析的输入流,按行解析 + * @param the input stream, parsed by line * @throws TC_Config_Exception * @return */ @@ -499,9 +640,12 @@ protected: /** * @brief create New Domain 生成子域. + * @brief Create New subdomain * * @param sName 域名称 - * @return 指向新生成的子域的指针 + * @param sName domain name + * @return 指向新生成的子域的指针 + * @return Pointer to the newly generated subfield * @throws TC_Config_Exception */ TC_ConfigDomain *newTcConfigDomain(const string& sName); @@ -510,6 +654,7 @@ protected: * @brief Search Domain 搜索域. * * @param sDomainName 参数名称,支持子域搜索 + * @param sDomainName param name, support the subdomain search * @return value */ TC_ConfigDomain *searchTcConfigDomain(const vector& domains); @@ -519,6 +664,7 @@ protected: /** * 根domain + * the root domain */ TC_ConfigDomain _root; }; diff --git a/util/include/util/tc_consistent_hash.h b/util/include/util/tc_consistent_hash.h index 053adff1e400572b94d4524db11facd8be8e7e1f..c4688f1d77e30658b6985ec91e1ff5f139b9544c 100644 --- a/util/include/util/tc_consistent_hash.h +++ b/util/include/util/tc_consistent_hash.h @@ -28,6 +28,7 @@ namespace tars /** * @file tc_consistent_hash.h * @brief 一致性hash算法类. + * @brief Consistency hash algorithm class. */ ///////////////////////////////////////////////// @@ -35,11 +36,13 @@ struct node_T { /** *节点hash值 + *node hash value */ unsigned int iHashCode; /** *节点下标 + *node subscript */ unsigned int iIndex; }; @@ -48,6 +51,7 @@ struct node_T /** * @brief 一致性hash算法类 + * @brief Consistency hash algorithm class. */ class TC_ConsistentHash { @@ -55,6 +59,7 @@ class TC_ConsistentHash /** * @brief 构造函数 + * @brief Constructor */ TC_ConsistentHash() { @@ -62,10 +67,14 @@ class TC_ConsistentHash /** * @brief 节点比较. + * @brief Node comparison. * * @param m1 node_T类型的对象,比较节点之一 + * @param m1 node_T type object, one of the compared nodes * @param m2 node_T类型的对象,比较节点之一 + * @param m2 node_T type object, one of the compared nodes * @return less or not 比较结果,less返回ture,否则返回false + * @return less or not. The result. If the result is 'less', returns true, else returns false. */ static bool less_hash(const node_T & m1, const node_T & m2) { @@ -74,10 +83,14 @@ class TC_ConsistentHash /** * @brief 增加节点. + * @brief the added node * * @param node 节点名称 + * @param node node name * @param index 节点的下标值 + * @param index the node subscript * @return 节点的hash值 + * @return node hash value */ unsigned addNode(const string & node, unsigned int index) { @@ -93,9 +106,12 @@ class TC_ConsistentHash /** * @brief 删除节点. + * @brief Delete the node. * * @param node 节点名称 + * @param node node name * @return 0 : 删除成功 -1 : 没有对应节点 + * @return 0 : delete successfully -1 : no corresponding nodes */ int removeNode(const string & node) { @@ -114,10 +130,14 @@ class TC_ConsistentHash /** * @brief 获取某key对应到的节点node的下标. + * @brief Get the node subscript which corresponds to a certain key. * * @param key key名称 + * @param key key name * @param iIndex 对应到的节点下标 + * @param iIndex the corresponding node subscript * @return 0:获取成功 -1:没有被添加的节点 + * @return 0:obtain successfully -1:no added nodes */ int getIndex(const string & key, unsigned int & iIndex) { @@ -156,9 +176,12 @@ class TC_ConsistentHash protected: /** * @brief 计算md5值的hash,分布范围在 0 -- 2^32-1. + * @brief Calculate the hash of the MD5 value, and the distribution range is 0--2^32-1. * * @param sMd5 md5值 + * @param sNd5 md5 value * @return hash值 + * @return hash value */ unsigned int hash_md5(const string & sMd5) { diff --git a/util/include/util/tc_consistent_hash_new.h b/util/include/util/tc_consistent_hash_new.h index 5ca9a6ca92c1a1e577c02b24955a79f1c6d9206f..fb6eef1701327bbb83b6b4eb9e3c7599c7cc21d8 100755 --- a/util/include/util/tc_consistent_hash_new.h +++ b/util/include/util/tc_consistent_hash_new.h @@ -34,6 +34,7 @@ enum TC_HashAlgorithmType /** * @brief hash 算法虚基类 + * @brief hash Algorithmic Virtual Base Class */ class TC_HashAlgorithm : public TC_HandleBase { @@ -50,6 +51,7 @@ typedef TC_AutoPtr TC_HashAlgorithmPtr; /** * @brief ketama hash 算法 + * @brief Ketama Hash Algorithm */ class TC_KetamaHashAlg : public TC_HashAlgorithm { @@ -60,6 +62,7 @@ public: /** * @brief 默认的 hash 算法 + * @brief Default Hash Algorithm */ class TC_DefaultHashAlg : public TC_HashAlgorithm { @@ -70,6 +73,7 @@ public: /** * @brief hash alg 工厂 + * @brief Hash Algorithm Factory */ class TC_HashAlgFactory { @@ -79,6 +83,7 @@ public: /** * @brief 一致性hash算法类 + * @brief Consistency Hash Algorithm Class */ class TC_ConsistentHashNew { @@ -88,76 +93,99 @@ public: { /** *节点hash值 + *node hash value */ int32_t iHashCode; /** *节点下标 + * node subscript */ unsigned int iIndex; }; /** * @brief 构造函数 + * @brief Constructor */ TC_ConsistentHashNew(); /** * @brief 构造函数 + * @brief Constructor */ TC_ConsistentHashNew(TC_HashAlgorithmType hashType); /** * @brief 排序 + * @brief Sort * * @param node 节点名称 + * @param node node name * @param index 节点的下标值 + * @param index node subscript value */ void sortNode(); /** * @brief 打印节点信息 + * @brief print node info * */ void printNode(); /** * @brief 增加节点. + * @brief add nodes * * @param node 节点名称 + * @param node node name * @param index 节点的下标值 + * @param index node subscript value * @param weight 节点的权重,默认为1 + * @param weight node weight, default value is 1 * @return 是否成功 + * @return whether it is successfull or not */ int addNode(const string & node, unsigned int index, int weight = 1); /** * @brief 获取某key对应到的节点node的下标. + * @brief Gets the subscript of the node to which a key corresponds. * * @param key key名称 + * @param key key name * @param iIndex 对应到的节点下标 + * @param iIndex the subscript of the node to which corresponds. * @return 0:获取成功 -1:没有被添加的节点 + * @return 0:obtain successfully -1:no nodes added */ int getIndex(const string & key, unsigned int & iIndex); /** * @brief 获取某hashcode对应到的节点node的下标. + * @brief Gets the subscript of the node to which a certain hashcode corresponds * * @param hashcode hashcode * @param iIndex 对应到的节点下标 + * @param iIndex the subscript of the node to which corresponds * @return 0:获取成功 -1:没有被添加的节点 + * @return 0:obtain successfully -1:no nodes added */ int getIndex(int32_t hashcode, unsigned int & iIndex); /** * @brief 获取当前hash列表的长度. + * @brief Get the length of the current hash list * * @return 长度值 + * @return length */ size_t size() { return _vHashList.size(); } /** * @brief 清空当前的hash列表. + * @brief Empty the current hash list. * */ void clear() { _vHashList.clear(); } diff --git a/util/include/util/tc_cron.h b/util/include/util/tc_cron.h index 580337f9f0b57d206281cdd5a6aa9d3c9fb425f0..b3a56db0f29660eaf4ca80b62274ee3fb188fa99 100644 --- a/util/include/util/tc_cron.h +++ b/util/include/util/tc_cron.h @@ -43,10 +43,14 @@ public: public: /** * @brief 创建一个cron对象 + * @brief Create a cron object * @return cron 对象 + * @return cron object */ // 字段分别为 + // The fields are: // 通配符以及含义 + // Wildcards and their meanings: // * all values selects all values within a field // - range specify ranges // , comma specify additional values @@ -54,6 +58,7 @@ public: // DAYS = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" }; // MONTHS = { "NIL", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" }; // 各类例子 + // Examples: // CRON Description // * * * * * * Every second // */5 * * * * * Every 5 seconds @@ -69,15 +74,21 @@ public: /** * @brief 获取cron对象的下一个时间点 + * @brief Get the next point in time for the cron object * @param cron 对象 + * @param cron object * @return 如果返回 INVALID_TIME,则是错误时间,否则返回正确的时间戳 + * @return If INVALID_TIME is returned, it is the wrong time. Otherwise the correct timestamp is returned. */ static std::time_t nextcron( const TC_Cron& cron, std::time_t timestamp); /** * @brief 获取cron对象的下一个时间点 + * @brief Get the next point in time for the cron object. * @param cron 对象 + * @param cron object * @return 如果返回 INVALID_TIME,则是错误时间,否则返回正确的时间戳 + * @return If INVALID_TIME is returned, it is the wrong time. Otherwise the correct timestamp is returned. */ static std::time_t nextcron(const TC_Cron& cron); @@ -117,18 +128,22 @@ public: protected: /** * @brief 判断是否包含字符 + * @brief Determine whether it includes characters. * @return true 包含;false 不包含 + * @return true include; false not include */ static bool contains(const std::string &text, char ch) ; /** * @brief 转换成crontab合法数字 + * @brief Convert to crontab legal number * @return cron_int */ static cron_int to_cron_int(const std::string& text); /** * @brief 时间格式转换函数 + * @brief Time format conversion function */ static std::time_t tm_to_time(std::tm& tmt); static std::tm* time_to_tm(std::time_t const* date, std::tm* const out); @@ -136,16 +151,19 @@ protected: protected: /** * @brief 替换周/月的字符为下标 + * @brief Replace week/month characters as Subscripts */ static std::string replaceOrdinals(std::string text, const std::vector & replacement); /** * @brief 获取时间范围,用于计算通配符 + * @brief Gets the time range for calculating wildcards. */ static std::pair makeRange(std::string field, cron_int minval, cron_int maxval); /** * @brief 设置crontab不同的位置标记 + * @brief Set different crontab location tags */ template static void setCronField(std::string value, std::bitset& target, cron_int minval, cron_int maxval); @@ -155,6 +173,7 @@ protected: /** * @brief 计算下一个时间戳 + * @brief Calculate the next timestamp */ template static size_t findNext(const std::bitset & target, std::tm& tmt, unsigned int minimum, unsigned int maximum, unsigned int value, @@ -164,6 +183,7 @@ protected: /** * @brief 位图控制函数 + * @brief Bitmap control function */ template static size_t nextSetbit(const std::bitset & target, size_t minimum, size_t maximum, size_t offset); diff --git a/util/include/util/tc_des.h b/util/include/util/tc_des.h index dbdd060ab566959c6e586eccec5a7678b9df8864..59505774d11a8cea939039fd995ce4d0ac887283 100644 --- a/util/include/util/tc_des.h +++ b/util/include/util/tc_des.h @@ -13,6 +13,7 @@ namespace tars /** * @file tc_des.h * @brief des加解密类(翻译至c代码) + * @brief DES encryption and decryption class (translated to C code) * * @author ruanshudong@qq.com */ @@ -21,6 +22,7 @@ namespace tars /** * @brief des异常. + * @brief des exception */ struct TC_DES_Exception : public TC_Exception { @@ -31,24 +33,34 @@ struct TC_DES_Exception : public TC_Exception /** * @brief des/3des加密解密源码, 不依赖任何库. + * @brief Use des/3des to encrypt and decrypt the source code, independent of any library. * * 在网上流行的d3des.h d3des.c修改完成. + * It is modified by the popular 'd3des.h' and 'd3des.c' on the web. * - * 对于des加密,8位密钥,不足8位的右补0x00,多余8位,只取左8位有效. + * 对于des加密,8位密钥,不足8位的右补0x00,多于8位,只取左8位有效. + * For des encryption, use 8-bit key. If it is less than 8 bits, right complete 0x00. If it is more than 8 bits, only the left 8 bits are valid. * * 加密内容8位补齐,补齐方式为:少1位补一个0x01,少2位补两个0x02,... + * The encrypted content follow 8-bit completion, the completion method is: less 1 bit to complete one 0x01, less 2 bits to complete two 0x02,... * * 本身已8位对齐的,后面补八个0x08. + * If itself is 8-bit aligned, complete eight '0x08' at the tail. * * 对于3des加解密,如下:只支持3des-ecb加密方式; + * For 3des encryption and decryption, only 3des-ecb encryption is supported; * * 24位密钥,不足24位的右补0x00,多余24位,只取左24位有效; + * For 24-bit key, if it is less than 24 bits, right complete 0x00. If it is more than 24 bits, only the left 24 bits are valid. * * 加密内容8位补齐,补齐方式为:少1位补一个0x01,少2位补两个0x02,... + * The encrypted content follow 8-bit completion, the completion method is: less 1 bit to complete one 0x01, less 2 bits to complete two 0x02,... * * 本身已8位对齐的,后面补八个0x08. + * If itself is 8-bit aligned, complete eight '0x08' at the tail. * * Key必须是null结束的字符串. + * The key must be a null-terminated string. * */ class TC_Des @@ -56,82 +68,117 @@ class TC_Des public: /** * @brief des加密. + * @brief des encryption * * @param key key, 8个字节 + * @param key key, 8 bits * @param sIn 输入buffer + * @param sIn input buffer * @param iInLen 输入buffer长度 + * @param iInLen input buffer length * @return string 加密后的内容 + * @return string, the encrypted content */ static string encrypt(const char *key, const char *sIn, size_t iInlen); /** * @brief des解密. + * @brief des decryption * * @param key key, 8个字节 + * @param key key, 8 bits * @param sIn 输入buffer + * @param sIn input buffer * @param iInlen 输入buffer长度 + * @param iInLen input buffer length * @return string 解码后的内容, 如果解密失败, 则为空 + * @return string, the decrypted content, if decryption failed, return null. */ static string decrypt(const char *key, const char *sIn, size_t iInlen); /** * @brief 3des加密. + * @brief 3des encryption * * @param key key, 24个字节 + * @param key key, 24 bits * @param sIn 输入buffer + * @param sIn input buffer * @param iInLen 输入buffer长度 + * @param iInLen input buffer length * @return string 加密后的内容 + * @return string, the encrypted content */ static string encrypt3(const char *key, const char *sIn, size_t iInlen); /** * @brief 3des解密. + * @brief 3des decryption * @param key key, 24个字节 + * @param key key, 24 bits * @param sIn 输入buffer + * @param sIn input buffer * @param iInlen 输入buffer长度 + * @param iInLen input buffer length * @return string解码后的内容, 如果解密失败, 则为空 + * @return string, the dcrypted content, if decryption failed, return null. */ static string decrypt3(const char *key, const char *sIn, size_t iInlen); /** * @brief 定义加密/解密 . + * @brief Define Encryption/Decryption */ enum { + /**Encryption*/ EN0 = 0, /**加密*/ + /**Decryption*/ DE1 = 1 /**解密*/ }; protected: /** * @brief 获取key. + * @brief Get key. * * @param key key值 + * @param key key value * @param mode 模式 :0代表加密, 1代表解密 + * @param mode mode : 0(encryption), 1(decryption) */ static void deskey(const char *key, short mode, uint32_t *k); /** * @brief des加密/解密. + * @brief DES Encryption/Decryption * * @param from 8个字节 + * @param from 8 bits * @param to 加密解密只有的8个字节 + * @param to encrypt and decrypt the only 8 bits. */ static void des(const char *from, char *to, uint32_t *KnL); /** * @brief 获取key. + * @brief Get key. * * @param key key值 + * @param key key value * @param mode 模式,0代表加密, 1代表解密 + * @param mode mode : 0(encryption), 1(decryption) */ static void des3key(const char *key, short mode, uint32_t *KnL, uint32_t *KnR, uint32_t *Kn3); /** * @brief 3des. + * @brief 3DES * * @param from 8个字节 + * @param from 8 bits * @param into 加密解密只有的8个字节 + * @param to encrypt and decrypt the only 8 bits. */ static void des3(const char *from, char *into, uint32_t *KnL, uint32_t *KnR, uint32_t *Kn3); diff --git a/util/include/util/tc_dyn_object.h b/util/include/util/tc_dyn_object.h index b1b6c6e2b36a0abe8a32bfb551628d2abebafd44..6a0096b3845297d8e60e44f6648c966303781876 100644 --- a/util/include/util/tc_dyn_object.h +++ b/util/include/util/tc_dyn_object.h @@ -25,12 +25,14 @@ namespace tars /** * @file tc_dyn_object.h * @brief 动态生成类. + * @brief Dynamic Generation Class. */ ///////////////////////////////////////////////// /** * @brief 动态生成类 + * @brief Dynamic Generation Class. */ class TC_DYN_Object; struct TC_DYN_RuntimeClass; diff --git a/util/include/util/tc_encoder.h b/util/include/util/tc_encoder.h index ef76969ee8ecf41d63776368c89fab82de93a8ac..0844469ec90e3d0ee7770d8c47525d5e84daedc1 100644 --- a/util/include/util/tc_encoder.h +++ b/util/include/util/tc_encoder.h @@ -27,6 +27,7 @@ namespace tars /** * @file tc_encoder.h * @brief 转码类 +* @brief Transcoder Class * * */ @@ -34,6 +35,7 @@ namespace tars /** * @brief 转码异常类 +* @brief Transcoder Exception Class */ struct TC_Encoder_Exception : public TC_Exception { @@ -44,12 +46,16 @@ struct TC_Encoder_Exception : public TC_Exception /** * @brief 该类提供基本常用编码的转换. +* @brief This class provides the transformation of basic common codes. * * Gbk到utf8之间的相互转码函数,通过静态函数提供. +* Transcoding functions between GBK and UTF8 are provided through static functions. * -* 1:GBK ==> UTF8的转换 +* 1:GBK ==> UTF8的转换 +* 1: The transformation from GBK to UTF8 * * 2:UTF8 ==> GBK的转换 +* 2: The transformation from UTF8 to GBK */ class TC_Encoder { @@ -57,18 +63,24 @@ public: /** * @brief gbk 转换到 utf8. + * @brief The transformation from GBK to UTF8. * * @param sIn 输入buffer* + * @param sIn input buffer* * @throws TC_Encoder_Exception * @return 转换后的utf8编码 + * @return the UTF8 encodeing after transformation */ static string gbk2utf8(const string &sIn); /** * @brief gbk 转换到 utf8. + * @brief The transformation from GBK to UTF8. * * @param sIn 输入buffer + * @param sIn input buffer * @param vtStr 输出gbk的vector + * @param vtStr output the GBK vector * @throws TC_Encoder_Exception * @return */ @@ -77,38 +89,57 @@ public: /** * @brief utf8 转换到 gbk. + * @brief The transformation from UTF8 to GBK. * * @param sIn 输入buffer + * @param sIn input buffer * @throws TC_Encoder_Exception * @return 转换后的gbk编码 + * @return the GBK encodeing after transformation */ static string utf82gbk(const string &sIn); /** * @brief 将string的\n替换掉,转义字符串中的某个字符 + * @brief Replace string '\n ' to escape a character in the string * * 缺省:\n 转换为 \r\0; \r转换为\, + * Default: '\n' is escaped to '\r\0'; '\r' is escaped to '\', * * 主要用于将string记录在一行,通常用于写bin-log的地方; + * Mainly used to record strings on one line, usually where 'bin-logs' are written; * @param str 待转换字符串 + * @param str the string to be escaped * @param f 需要转义的字符 + * @param f the character to be escaped * @param t 转义后的字符 + * @param t the escaped character * @param u 借用的转义符 + * @param u the borrowed escape character * @return str 转换后的字符串 + * @return str the escaped string */ static string transTo(const string& str, char f = '\n', char t = '\r', char u = '\0'); /** * @brief 从替换的数据恢复源数据,将 transTo 的字符串还原, + * @brief Restore source data from the replaced data, restore the string of transTo. * * 缺省:\r\0 还原为\n,\r\r还原为, + * Default: '\r\0' is escaped to '\n'; '\r\r' is escaped to, * * 主要用于将string记录在一行,通常用于写bin-log的地方 + * It is mainly used to record string on one line,usally used to where the bin-log written. * @param str 待还原的字符串(必须是transTo后得到的字符串) + * @param str the string to be resroed(must be the string after transTo) * @param f 被转义的字符 + * @param f the escaped character * @param t 转义后的字符 + * @param t the character after being escaped * @param u 借用的转义符 + * @param u the borrowed escaped character * @return str 还原后的字符串 + * @return str the restored string */ static string transFrom(const string& str, char f = '\n', char t = '\r', char u = '\0'); @@ -116,11 +147,16 @@ protected: /** * @brief utf8 转换到 gbk. + * @brief The transformation from UTF8 to GBK. * * @param sOut 输出buffer + * @param sOut output buffer * @param iMaxOutLen 输出buffer最大的长度/sOut的长度 + * @param iMaxOutLen output the max buffer length/ sOut length * @param sIn 输入buffer + * @param sIn input buffer * @param iInLen 输入buffer长度 + * @param iInLen input buffer length * @throws TC_Encoder_Exception * @return */ diff --git a/util/include/util/tc_epoll_server.h b/util/include/util/tc_epoll_server.h index 3a46cfddd624905c31bbf4fd4b8c5d651db97ca4..290bffe6a40fec6af321b0377583a0dbbfa618e5 100644 --- a/util/include/util/tc_epoll_server.h +++ b/util/include/util/tc_epoll_server.h @@ -46,14 +46,19 @@ namespace tars /** * @file tc_epoll_server.h * @brief EpollServer类 + * @brief EpollServer Class * */ ///////////////////////////////////////////////// /** * Server基类 + * Server Basic Class * 注册协议解析器 + * Register Protocol Resolver * 注册逻辑处理器 + * Register Logical Processor * 注册管理端口处理器 + * Register Management Port Processor */ class PropertyReport; @@ -64,18 +69,25 @@ public: enum EM_CLOSE_T { + /**Client active shutdown*/ EM_CLIENT_CLOSE = 0, //客户端主动关闭 + /**The service-side business proactively calls 'close' to close the connection, + * or the framework proactively closes the connection due to an exception.*/ EM_SERVER_CLOSE = 1, //服务端业务主动调用close关闭连接,或者框架因某种异常主动关闭连接 + /**Connection timed out, server actively closed*/ EM_SERVER_TIMEOUT_CLOSE = 2 //连接超时了,服务端主动关闭 }; enum { + /**Empty connection timeout (ms)*/ MIN_EMPTY_CONN_TIMEOUT = 2*1000, /*空链接超时时间(ms)*/ + /**The size of received buffer of the default data*/ DEFAULT_RECV_BUFFERSIZE = 64*1024 /*缺省数据接收buffer的大小*/ }; //定义加入到网络线程的fd类别 + //Define the FD categories added to network threads enum CONN_TYPE { TCP_CONNECTION = 0, @@ -85,6 +97,8 @@ public: /** * 定义协议解析接口的操作对象 * 注意必须是线程安全的或是可以重入的 + * Define the Operating Object of the Protocol Resolution Interface + * Note that it must be thread safe or reentrant */ typedef std::function&)> header_filter_functor; @@ -101,6 +115,8 @@ public: /** * 发送包的上下文 * 由RecvContext创建出来 + * Context of sending packets + * Created by RecvContext */ class SendContext { @@ -122,13 +138,16 @@ public: protected: shared_ptr _context; + /**Send package is valid. Command: 'c', close FD; 's', data need to be sent*/ char _cmd; /**send包才有效, 命令:'c',关闭fd; 's',有数据需要发送*/ + /**Sent context*/ shared_ptr _sbuffer; /**发送的内容*/ }; //////////////////////////////////////////////////////////////////////////// /** * 接收包的上下文 + * Context of receiving package */ class RecvContext : public std::enable_shared_from_this { @@ -156,98 +175,129 @@ public: shared_ptr createCloseContext() { return std::make_shared(shared_from_this(), 'c'); } protected: + /**Connection Label*/ uint32_t _uid; /**连接标示*/ - string _ip; /**远程连接的ip*/ - uint16_t _port; /**远程连接的端口*/ - int _fd; /*保存产生该消息的fd,用于回包时选择网络线程*/ - BindAdapterPtr _adapter; /**标识哪一个adapter的消息*/ - vector _rbuffer; /**接收的内容*/ - bool _isOverload = false; /**是否已过载 */ - bool _isClosed = false; /**是否已关闭*/ - int _closeType; /*如果是关闭消息包,则标识关闭类型,0:表示客户端主动关闭;1:服务端主动关闭;2:连接超时服务端主动关闭*/ - int64_t _recvTimeStamp; /**接收到数据的时间*/ + /**IP for remote connection*/ + string _ip; /**远程连接的ip*/ + /**Port for remote connection*/ + uint16_t _port; /**远程连接的端口*/ + /**Save the FD that generated the message to select the network thread when returning the package*/ + int _fd; /*保存产生该消息的fd,用于回包时选择网络线程*/ + /**Message identifying which adapter*/ + BindAdapterPtr _adapter; /**标识哪一个adapter的消息*/ + /**Received message*/ + vector _rbuffer; /**接收的内容*/ + /**Is overloaded*/ + bool _isOverload = false; /**是否已过载 */ + /**Is closed*/ + bool _isClosed = false; /**是否已关闭*/ + /**If the message package is closed, the type of closure is identified, + * 0: the client actively closes, + * 1: the server actively closes, + * 2: the connection timeout server actively closes. + * */ + int _closeType; /*如果是关闭消息包,则标识关闭类型,0:表示客户端主动关闭;1:服务端主动关闭;2:连接超时服务端主动关闭*/ + /**Time to receive data*/ + int64_t _recvTimeStamp; /**接收到数据的时间*/ }; - typedef TC_CasQueue> recv_queue; - typedef TC_CasQueue> send_queue; +// typedef TC_CasQueue> recv_queue; + typedef TC_ThreadQueue> recv_queue; +// typedef TC_CasQueue> send_queue; + typedef TC_ThreadQueue> send_queue; typedef recv_queue::queue_type recv_queue_type; - //////////////////////////////////////////////////////////////////////////// - /** - * 链接状态 - */ - struct ConnStatus - { - string ip; - int32_t uid; - uint16_t port; - int timeout; - int iLastRefreshTime; - }; + //////////////////////////////////////////////////////////////////////////// + /** + * 链接状态 + * Connection state + */ + struct ConnStatus + { + string ip; + int32_t uid; + uint16_t port; + int timeout; + int iLastRefreshTime; + size_t recvBufferSize; + size_t sendBufferSize; + }; //////////////////////////////////////////////////////////////////////////// /** * @brief 定义服务逻辑处理的接口 + * @brief Define interfaces for logical processing of services * */ /** * 服务的逻辑处理代码 + * Logical Processing Code for Services */ class Handle : public TC_Thread, public TC_HandleBase { public: /** * 构造, 默认没有请求, 等待10s + * Constructor, default no request, wait 10s */ Handle(); /** * 析构函数 + * Destructor */ virtual ~Handle(); /** * 获取服务 + * Get Service * @return TC_EpollServer* */ TC_EpollServer* getEpollServer() const { return _pEpollServer; }; /** * 获取adapter + * Get adapter * @return */ BindAdapter *getBindAdapter() const { return _bindAdapter; } /** * 获取Handle的索引(0~handle个数-1) + * Get the index of Handle(0~handle count-1) * @return */ uint32_t getHandleIndex() const { return _handleIndex; } /** * 设置网络线程 + * Set up network thread */ void setNetThread(NetThread *netThread); /** * 获取网络线程 + * Get network thread * @return */ NetThread *getNetThread() { return _netThread; } /** * 处理 + * Process */ void process(shared_ptr data); /** * 线程处理方法 + * Thread processing method */ virtual void run(); public: /** * 发送数据 + * Send data * @param stRecvData * @param sSendBuffer */ @@ -255,52 +305,64 @@ public: /** * 关闭链接 + * Close connection * @param stRecvData */ void close(const shared_ptr &data); /** * 设置等待时间 + * Set up waiting time * @param iWaitTime */ void setWaitTime(uint32_t iWaitTime); /** * 对象初始化 + * Object initialization */ virtual void initialize() {}; /** * 唤醒handle对应的处理线程 + * Wake up the process thread corresponding to the handle */ virtual void notifyFilter(); /** * 心跳(每处理完一个请求或者等待请求超时都会调用一次) + * Heartbeat(Called every time a request has been processed or the waiting request has timed out) */ virtual void heartbeat() {} protected: /** * 具体的处理逻辑 + * Specific processing logic */ virtual void handleImp(); /** * 处理函数 + * Processing Function * @param stRecvData: 接收到的数据 + * @param stRecvData: received data */ virtual void handle(const shared_ptr &data) = 0; /** * 处理超时数据, 即数据在队列中的时间已经超过 * 默认直接关闭连接 + * Processing timeout data, i.e. data has been queued longer than + * Close connection directly by default * @param stRecvData: 接收到的数据 + * @param stRecvData: received data */ virtual void handleTimeout(const shared_ptr &data); /** * 处理连接关闭通知,包括 + * Handle connection shutdown notifications, including: * 1.close by peer * 2.recv/send fail * 3.close by timeout or overload @@ -311,68 +373,84 @@ public: /** * 处理overload数据 即数据队列中长度已经超过允许值 * 默认直接关闭连接 + * Processing overload data means that the length of the data queue has exceeded the allowable value + * Close connection directly by default * @param stRecvData: 接收到的数据 + * @param stRecvData: received data */ virtual void handleOverload(const shared_ptr &data); /** * 处理异步回调队列 + * Handle asynchronous callback queues + */ virtual void handleAsyncResponse() {} /** * handleFilter拆分的第二部分,处理用户自有数据 * 非游戏逻辑可忽略bExpectIdle参数 + * The second part of handleFilter splitting, dealing with user-owned data + * Non-game logic ignores bExpectIdle parameter */ virtual void handleCustomMessage(bool bExpectIdle = false) {} /** * 线程已经启动, 进入具体处理前调用 + * Thread has been started and called before entering specific processing */ virtual void startHandle() {} /** * 线程马上要退出时调用 + * Call when the thread is about to exit */ virtual void stopHandle() {} /** * 是否所有的Adpater队列都为空 + * Whether all adapter queues are empty. * @return bool */ virtual bool allAdapterIsEmpty(); /** * 是否所有的servant都没有resp消息待处理 + * Whether all servant don't have resp message to deal. * @return bool */ virtual bool allFilterIsEmpty(); /** * 设置服务 + * Set up service * @param pEpollServer */ void setEpollServer(TC_EpollServer *pEpollServer); /** * 设置Adapter + * Set up Apdater * @param pEpollServer */ void setBindAdapter(BindAdapter* bindAdapter); /** * 设置index + * Set up index * @param index */ void setHandleIndex(uint32_t index); /** * 等待在队列上 + * On the waiting queue */ void wait(); /** * 从队列中获取数据 + * Receive data from the queue * @param recv * @return */ @@ -380,31 +458,37 @@ public: /** * 友元类 + * Friend Class */ friend class BindAdapter; protected: /** * 服务 + * Service */ TC_EpollServer *_pEpollServer; /** * handle对应的网路线程(网络线程和handle线程合并的情况下有效) + * Network threads corresponding to handle (valid when network threads and handle threads are merged) */ NetThread *_netThread = NULL; /** * 所属handle组 + * The handle group to which one belongs */ BindAdapter* _bindAdapter; /** * 等待时间 + * Waiting time */ uint32_t _iWaitTime; /** * Handle的索引 + * Index of the Handle */ uint32_t _handleIndex; @@ -415,21 +499,28 @@ public: //////////////////////////////////////////////////////////////////////////// // 服务端口管理,监听socket信息 + // Service port management, listening for socket information class BindAdapter : public TC_HandleBase { public: /** * 缺省的一些定义 + * Defualt definitions */ enum { + /**Flow*/ DEFAULT_QUEUE_CAP = 10*1024, /**流量*/ + /**Queue minimum timeout (ms)*/ MIN_QUEUE_TIMEOUT = 3*1000, /**队列最小超时时间(ms)*/ + /**Default maximum connections*/ DEFAULT_MAX_CONN = 1024, /**缺省最大连接数*/ + /**Default queue timeout (ms)*/ DEFAULT_QUEUE_TIMEOUT = 60*1000, /**缺省的队列超时时间(ms)*/ }; /** * 顺序 + * Order */ enum EOrder { @@ -439,96 +530,113 @@ public: /** * 数据队列 + * Data Queue */ struct DataQueue { /** * 接收的数据队列 + * Received data queue */ recv_queue _rbuffer; /** * 锁 + * Lock */ TC_ThreadLock _monitor; }; /** * 构造函数 + * Constructor */ BindAdapter(TC_EpollServer *pEpollServer); /** * 析够函数 + * Destructor */ ~BindAdapter(); /** * 设置需要手工监听 + * Set requires manual listening */ void enableManualListen() { _manualListen = true; } /** * 是否手工监听端口 + * Whether to manual listen the port or not * @return */ bool isManualListen() const { return _manualListen; } /** * 手工绑定端口 + * Manual port binding */ void manualListen(); /** * 设置adapter name + * Set up adapter name * @param name */ void setName(const string &name); /** * 获取adapter name + * Get adapter name * @return string */ string getName() const; /** * 增加处理线程对应的接收队列 + * Add the corresponding receiving queue for processing threads * @return string */ void initThreadRecvQueue(uint32_t handeIndex); /** * 获取queue capacity + * Get queue capacity * @return int */ int getQueueCapacity() const; /** * 设置queue capacity + * Set up queue capacity * @param n */ void setQueueCapacity(int n); /** * 设置协议名称 + * Set up the protocol name * @param name */ void setProtocolName(const string& name); /** * 获取协议名称 + * Get the protocol name * @return const string& */ const string& getProtocolName(); /** * 是否tars协议 + * Whether it is the tars protocol * @return bool */ bool isTarsProtocol(); /** * 判断是否需要过载保护 + * Determine whether it needs overload protection * @return bool */ int isOverloadorDiscard(); @@ -536,96 +644,116 @@ public: /** * 设置消息在队列中的超时时间, t为毫秒 * (超时时间精度只能是s) + * Set the timeout time of the message in the queue, t is milliseconds + * (timeout precision can only be s) + * * @param t */ void setQueueTimeout(int t); /** * 获取消息在队列中的超时时间, 毫秒 + * Get timeout of message in queue, MS * @return int */ int getQueueTimeout() const; /** * 设置endpoint + * Set up endpoint * @param str */ void setEndpoint(const string &str); /** * 获取ip + * Get ip * @return const string& */ TC_Endpoint getEndpoint() const; /** * 监听socket + * Listen socket * @return TC_Socket */ TC_Socket &getSocket(); /** * 设置最大连接数 + * Set the maximum connection number * @param iMaxConns */ void setMaxConns(int iMaxConns); /** * 获取最大连接数 + * Get the maximum connection number * @return size_t */ size_t getMaxConns() const; /** * 设置HeartBeat时间 + * Set the HeartBeat time * @param n */ void setHeartBeatTime(time_t t); /** * 获取HeartBeat时间 + * Get the HeartBeat time * @return size_t */ time_t getHeartBeatTime() const; /** * 设置allow deny次序 + * Set the allow deny order * @param eOrder */ void setOrder(EOrder eOrder); /** * 设置允许ip + * Set allowed ip * @param vtAllow */ void setAllow(const vector &vtAllow); /** * 设置禁止ip + * Set the disabled ip * @param vtDeny */ void setDeny(const vector &vtDeny); /** * 获取允许ip + * Get the allowed ip * @return vector: ip列表 + * @return vector: ip list */ const vector &getAllow() const; /** * 获取禁止ip + * Get the disable ip * @return vector: ip列表 + * @return vector: ip list */ const vector &getDeny() const; /** * 获取allow deny次序 + * Get the allow deny order * @return EOrder */ EOrder getOrder() const; /** * 是否Ip被允许 + * Whether the ip is allowed or not * @param ip * @return bool */ @@ -633,40 +761,47 @@ public: /** * 是否超过了最大连接数 + * Whether it exceeds the maximum connection number * @return bool */ bool isLimitMaxConnection() const; /** * 减少当前连接数 + * Reduce current connections */ void decreaseNowConnection(); - /** - * 增加当前连接数 - */ - void increaseNowConnection(); + /** + * 增加当前连接数 + * Increase current connections + */ + void increaseNowConnection(); - /** - * 获取所有链接状态 - * @return ConnStatus - */ - vector getConnStatus(); + /** + * 获取所有链接状态 + * Get all connection states + * @return ConnStatus + */ + vector getConnStatus(); - /** - * 获取当前连接数 - * @return int - */ - int getNowConnection() const; + /** + * 获取当前连接数 + * Get current connections + * @return int + */ + int getNowConnection() const; - /** - * 获取EpollServer - * @return TC_EpollServer* - */ - TC_EpollServer* getEpollServer() const { return _pEpollServer; } + /** + * 获取服务 + * Get service + * @return TC_EpollServer* + */ + TC_EpollServer* getEpollServer() const { return _pEpollServer; }; /** * 获取对应的网络线程 + * Get the corresponding network thread * @param fd * @return */ @@ -674,44 +809,69 @@ public: /** * 注册协议解析器 + * Registration Protocol parser * @param pp */ void setProtocol(const TC_NetWorkBuffer::protocol_functor& pf, int iHeaderLen = 0, const header_filter_functor& hf = echo_header_filter); - /** - * 获取协议解析器 - * @return protocol_functor& - */ - TC_NetWorkBuffer::protocol_functor &getProtocol(); + /** + * 获取协议解析器 + * Get Registration Protocol parser + * @return protocol_functor& + */ + TC_NetWorkBuffer::protocol_functor &getProtocol(); - /** - * 解析包头处理对象 - * @return protocol_functor& - */ - header_filter_functor &getHeaderFilterFunctor(); + /** + * 解析包头处理对象 + * Resolve Package Header Processing Objects + * @return protocol_functor& + */ + header_filter_functor &getHeaderFilterFunctor(); /** * 增加数据到队列中 + * Add data to the queue * @param vtRecvData * @param bPushBack 后端插入 + * @param bPushBack Backend insert * @param sBuffer */ void insertRecvQueue(const shared_ptr &recv);//, bool bPushBack = true); /** * 等待数据 + * Wait for data * @return bool */ bool waitForRecvQueue(uint32_t handleIndex, shared_ptr &recv); - /** - * 接收队列的大小 - * @return size_t - */ - size_t getRecvBufferSize() const; + /** + * 接收队列的大小 + * Size of the received queue + * @return size_t + */ + size_t getRecvBufferSize() const; + + /** + * 发送队列的大小 + * Size of the sent queue + * @return size_t + */ + size_t getSendBufferSize() const; + + /** + * add send buffer size + */ + inline void increaseSendBufferSize() { ++_iSendBufferSize; } + + /** + * increase send buffer size + */ + inline void decreaseSendBufferSize(size_t s = 1) { _iSendBufferSize.fetch_sub(s); } /** * 默认的协议解析类, 直接echo + * Default protocol resolution class, direct echo * @param r * @param o * @return int @@ -720,6 +880,7 @@ public: /** * 默认的包头处理 + * Default header handling * @param i * @param o * @return int @@ -728,17 +889,20 @@ public: /** * 获取需要过滤的包头长度 + * Get the header length that needs to be filtered */ int getHeaderFilterLen(); /** * 所属handle组的handle数(每个handle一个对象) + * Number of handles belonging to the handle group (one object per handle) * @return int */ int getHandleNum(); /** * 初始化处理线程,线程将会启动 + * Initialize the processing thread, which will start */ template void setHandle(size_t n) { @@ -774,6 +938,7 @@ public: /** * 获取第几个句柄 + * Get the index of the handle * @param index * @return */ @@ -783,55 +948,77 @@ public: return _handles[index]; } - // /** - // * 设置服务端回包缓存的大小限制 - // */ - // void setBackPacketBuffLimit(size_t iLimitSize); + /* + * 设置服务端积压缓存的大小限制(超过大小启用) + * Set the size limit of the server's backlog cache (exceeding the size enabled) + */ + void setBackPacketBuffLimit(size_t iLimitSize) { _iBackPacketBuffLimit = iLimitSize; } - // /** - // * 获取服务端回包缓存的大小限制 - // */ - // size_t getBackPacketBuffLimit(); + /** + * 获取服务端回包缓存的大小限制(超过大小启用) + * Get the size limit of the server-side packet back cache (exceeding the size enabled) + */ + size_t getBackPacketBuffLimit() const { return _iBackPacketBuffLimit; } + + /* + * 设置服务端5/s最低发送字节 + * Set the Server 5/s Minimum Sending Bytes + */ + void setBackPacketBuffMin(size_t iMinLimit) { _iBackPacketBuffMin = iMinLimit; } + /** + * 获取服务端5/s最低发送字节 + * Get the Server 5/s Minimum Sending Bytes + */ + size_t getBackPacketBuffMin() const { return _iBackPacketBuffMin; } /** * 获取服务端接收队列(如果_rnbuffer有多个, 则根据调用者的线程id来hash获取) + * Get the server receive queue (if there's more than one _rnbuffer, get from the hash based on the caller's thread id) + * */ recv_queue &getRecvQueue(uint32_t handleIndex); /** * 获取handles + * Get handles */ const vector &getHandles() { return _handles; } /** * 是否是队列模式(默认是False的) + * Whether it is the queue mode (Defualt false) */ bool isQueueMode() const { return _queueMode; } /** * 开启队列模式(同一个连接的请求, 落在同一个handle处理线程中) + * Open queue mode (The requests from the same connecion will fall in the same handle processing thread ) */ void enableQueueMode() { _queueMode = true; } /** * 等待队列数据 + * Wait for the queue data */ void waitAtQueue(uint32_t handleIndex, uint32_t waitTime); /** * 通知某个具体handle醒过来 + * Notify a specific handle to wake up * @param handleIndex */ void notifyHandle(uint32_t handleIndex); /** * 设置close回调函数 + * Set close callback function */ void setOnClose(const close_functor& f) { _closeFunc = f; } /** * 注册鉴权包裹函数 + * Regist Authentication Package Function * @param apwf */ void setAuthProcessWrapper(const auth_process_wrapper_functor& apwf) { _authWrapper = apwf; } @@ -849,6 +1036,7 @@ public: private: /** * 获取等待的队列锁 + * Get the waiting queue lock * @return */ TC_ThreadLock &getLock(uint32_t handleIndex); @@ -856,6 +1044,7 @@ public: public: //统计上报的对象 + //Count reporting objects PropertyReport * _pReportQueue = NULL; PropertyReport * _pReportConRate = NULL; PropertyReport * _pReportTimeoutNum = NULL; @@ -865,71 +1054,85 @@ public: /** * 加锁 + * Add lock */ mutable std::mutex _mutex; /** * 服务 + * Service */ TC_EpollServer *_pEpollServer = NULL; /** * Adapter所用的HandleGroup + * the HandleGroup used by Adapter */ vector _handles; /** * 协议解析 + * Destruct the protocol */ TC_NetWorkBuffer::protocol_functor _pf; /** * 首个数据包包头过滤 + * First packet header filtering */ header_filter_functor _hf; /** * adapter的名字 + * adapter name */ string _name; /** * 监听fd + * listen fd */ TC_Socket _s; /** * 绑定的IP + * binded ip */ TC_Endpoint _ep; /** * 最大连接数 + * the maximum number of connections */ int _iMaxConns; /** * 当前连接数 + * the current number of connections */ std::atomic _iCurConns; /** * Handle个数 + * the number of Handle */ size_t _iHandleNum; /** * 允许的Order + * the Allowed Order */ volatile EOrder _eOrder; /** * 允许的ip + * the Allowed IP */ vector _vtAllow; /** * 禁止的ip + * the Disabled IP */ vector _vtDeny; @@ -937,55 +1140,83 @@ public: * 每个线程都有自己的队列 * 0: 给共享队列模式时使用 * 1~handle个数: 队列模式时使用 + * Every thread has its own queue. + * 0: Use when sharing queue mode + * 1~handle count: Use when queue mode */ vector> _threadDataQueue; /** * 接收队列数据总个数 + * the total amount of the received queue data */ - atomic _iBufferSize{0}; + atomic _iRecvBufferSize{0}; - /** - * 队列最大容量 - */ - int _iQueueCapacity; + /** + * 发送队列数据总个数 + * the total amount of the sent queue data + */ + atomic _iSendBufferSize{0}; + + /** + * 队列最大容量 + * the maximum capacity of the queue + */ + int _iQueueCapacity; /** * 消息超时时间(从入队列到出队列间隔)(毫秒) + * Message timeout (from queue entry to queue exit interval) (milliseconds) */ int _iQueueTimeout; /** * 首个数据包包头长度 + * First packet header length */ int _iHeaderLen; /** * 上次心跳发送时间 + * Last heartbeat sent time */ volatile time_t _iHeartBeatTime; /** * 协议名称,缺省为"tars" + * Protocol name, default is "tars" */ string _protocolName; - // 回包缓存限制大小 - // size_t _iBackPacketBuffLimit; + /** + * 回包缓存限制大小 + * Packet Back Cache Limit Size + */ + size_t _iBackPacketBuffLimit = 0; + + /** + * 回包速度最低限制(5/s), 默认1K + * Minimum Packet Return Speed Limit (5/s), default 1K + */ + size_t _iBackPacketBuffMin = 1024; //队列模式 + //Queue Mode bool _queueMode = false; //listen模式 + //Listen Mode bool _manualListen = false; /** * 包裹认证函数,不能为空 + * Package authentication function, cannot be empty */ auth_process_wrapper_functor _authWrapper; /** * 该obj的AK SK + * the AK SK of the object */ std::string _accessKey; std::string _secretKey; @@ -998,14 +1229,17 @@ public: shared_ptr _ctx; #endif //连接关闭的回调函数 + //Callback function with connection closed close_functor _closeFunc; }; //////////////////////////////////////////////////////////////////////////// // 服务连接管理 + // Service Connection Management /** * 建立连接的socket信息 + * Socket information for establishing connections */ class Connection { @@ -1018,6 +1252,7 @@ public: /** * 构造函数 + * Constructor * @param lfd * @param s * @param ip @@ -1027,28 +1262,34 @@ public: /** * udp连接 + * UDP connection * @param fd */ Connection(BindAdapter *pBindAdapter, int fd); /** * 析构函数 + * Destructor */ virtual ~Connection(); /** * 链接所属的adapter + * the adapter of the connection */ BindAdapterPtr& getBindAdapter() { return _pBindAdapter; } /** * 初始化 + * Initialization * @param id, 连接的唯一id + * @param id, the connection unique id */ void init(unsigned int uid) { _uid = uid; } /** * 获取连接超时时间 + * Get connection timeout * * @return int */ @@ -1056,6 +1297,7 @@ public: /** * 获取线程的惟一id + * Get thread unique id * * @return unsigned int */ @@ -1063,6 +1305,7 @@ public: /** * 获取监听fd + * Get listening id * * @return int */ @@ -1070,6 +1313,7 @@ public: /** * 当前连接fd + * Current connection fd * * @return int */ @@ -1077,6 +1321,7 @@ public: /** * 是否有效 + * Whether it is valid * * @return bool */ @@ -1084,6 +1329,7 @@ public: /** * 远程IP + * Remote IP * * @return string */ @@ -1091,6 +1337,7 @@ public: /** * 远程端口 + * Remote Port * * @return uint16_t */ @@ -1098,21 +1345,25 @@ public: /** * 设置首个数据包包头需要过滤的字节数 + * Set the number of bytes the first packet header needs to filter */ void setHeaderFilterLen(int iHeaderLen) { _iHeaderLen = iHeaderLen; } /** * 设置关闭,发送完当前数据就关闭连接 + * Set shutdown to close connection after sending current data */ bool setClose(); /** * 获取连接类型 + * Get the type of the connection */ EnumConnectionType getType() const { return _enType; } /** * 是否是空连接 + * Whether there's empty connection. */ bool isEmptyConn() const {return _bEmptyConn;} @@ -1121,76 +1372,102 @@ public: */ void tryInitAuthState(int initState); + /** + * 接收数据buffer + * Receive data buffer + */ + TC_NetWorkBuffer &getRecvBuffer() { return _recvBuffer; } + + /** + * 发送数据buffer + * Send data buffer + */ + TC_NetWorkBuffer &getSendBuffer() { return _sendBuffer; } + + /** + * 发送buffer里面数据 + * Send the data in the bufer + * @return + */ + int sendBuffer(); + friend class NetThread; protected: /** * 关闭连接 + * Close the connection * @param fd */ void close(); - /** - * 发送TCP - */ - int sendTcp(const shared_ptr &data); - - /** - * 发送Udp - */ - int sendUdp(const shared_ptr &data); +// /** +// * 发送TCP +// * Send TCP +// */ +// int sendTcp(const shared_ptr &data); +// +// /** +// * 发送Udp +// * Send UDP +// */ +// int sendUdp(const shared_ptr &data); /** * 添加发送buffer + * Add sanding buffer * @param buffer * @return int, -1:发送出错, 0:无数据, 1:发送完毕, 2:还有数据 + * @return int, -1: sending error, 0: no data, 1: send completely, 2: data retains */ int send(const shared_ptr &data); - /** - * 发送buffer里面数据 - * @return - */ - int sendBuffer(); - /** * 读取数据 + * Read data * @param fd * @return int, -1:接收出错, 0:接收不全, 1:接收到一个完整包 + * @return int, -1: received error, 0: not receive completely, 1: receive a complete package */ int recv(); /** * 接收TCP + * Receive TCP */ int recvTcp(); /** * 接收Udp + * Receive UDP */ int recvUdp(); /** * 解析协议 + * Destruct protocol * @param o */ int parseProtocol(TC_NetWorkBuffer &rbuf); /** * 增加数据到队列中 + * Add data to the queue * @param vtRecvData */ void insertRecvQueue(const shared_ptr &recv); /** * 对于udp方式的连接,分配指定大小的接收缓冲区 + * For udp-mode connections, allocate receive buffers of a specified size *@param nSize */ bool setRecvBuffer(size_t nSize=DEFAULT_RECV_BUFFERSIZE); /** * 是否是tcp连接 + * Whether it is TCP connection. * @return */ bool isTcp() const { return _lfd != -1; } @@ -1198,6 +1475,7 @@ public: public: /** * 最后刷新时间 + * Last refresh time */ time_t _iLastRefreshTime; @@ -1205,6 +1483,7 @@ public: /** * 适配器 + * Adapter */ BindAdapterPtr _pBindAdapter; @@ -1215,16 +1494,19 @@ public: /** * 连接的唯一编号 + * the unique id of the connection */ volatile uint32_t _uid; /** * 监听的socket + * Listening socket */ int _lfd; /** * 超时时间 + * Timeout */ int _timeout; @@ -1235,31 +1517,55 @@ public: /** * 端口 + * Port */ uint16_t _port; /** * 接收数据buffer + * the buffer to receive data */ TC_NetWorkBuffer _recvBuffer; /** * 发送数据buffer + * the buffer to send data */ TC_NetWorkBuffer _sendBuffer; - /** - * 需要过滤的头部字节数 - */ - int _iHeaderLen; + /** + * 发送数据 + * Send data + */ + size_t _sendBufferSize = 0; + + /** + * 检查时间 + * Check time + */ + time_t _lastCheckTime = 0; + + /** + * 发送的检查<已经发送数据, 剩余buffer大小> + * Check Sent + */ + vector> _checkSend; + + /** + * 需要过滤的头部字节数 + * Number of header bytes to filter + */ + int _iHeaderLen; /** * 发送完当前数据就关闭连接 + * Close connection after sending current data */ bool _bClose; /** * 连接类型 + * Connection Type */ EnumConnectionType _enType; @@ -1267,6 +1573,7 @@ public: /* *接收数据的临时buffer,加这个目的是对udp接收数据包大小进行设置 + *Temporary buffer to receive data, plus this is to set the UDP receive packet size */ char *_pRecvBuffer = NULL; @@ -1275,6 +1582,7 @@ public: public: /* *该连接的鉴权状态 + *Authentication status of the connection */ int _authState; /* @@ -1288,28 +1596,33 @@ public: //////////////////////////////////////////////////////////////////////////// /** * 带有时间链表的map + * Map with Time Chain Table */ class ConnectionList { public: /** * 构造函数 + * Constructor */ ConnectionList(NetThread *pEpollServer); /** * 析够函数 + * Destructor */ ~ConnectionList() { if(_vConn) { delete[] _vConn; } } /** * 初始化大小 + * Initial size * @param size */ void init(uint32_t size, uint32_t iIndex = 0); /** * 获取惟一ID + * Get the unique ID * * @return unsigned int */ @@ -1317,6 +1630,7 @@ public: /** * 添加连接 + * Add Connection * @param cPtr * @param iTimeOutStamp */ @@ -1324,18 +1638,22 @@ public: /** * 刷新时间链 + * Refresh the connectiom * @param uid * @param iTimeOutStamp, 超时时间点 + * @param iTimeOutStamp, Timeout Point */ void refresh(uint32_t uid, time_t iTimeOutStamp); /** * 检查超时数据 + * Check Timeout */ void checkTimeout(time_t iCurTime); /** * 获取某个监听端口的连接 + * Get a connection to a listening port * @param lfd * @return vector */ @@ -1343,6 +1661,7 @@ public: /** * 获取某一个连接 + * Get a certain connection * @param p * @return T */ @@ -1350,12 +1669,14 @@ public: /** * 删除连接 + * Delete connection * @param uid */ void del(uint32_t uid); /** * 大小 + * Size * @return size_t */ size_t size(); @@ -1365,6 +1686,7 @@ public: /** * 内部删除, 不加锁 + * Internal Delete, No Lock * @param uid */ void _del(uint32_t uid); @@ -1372,46 +1694,55 @@ public: protected: /** * 无锁 + * No Lock */ - TC_SpinLock _mutex; + TC_ThreadMutex _mutex; - /** - * 服务 - */ - NetThread *_pEpollServer; + /** + * 服务 + * Service + */ + NetThread *_pEpollServer; /** * 总计连接数 + * Total connection amount */ volatile uint32_t _total; /** * 空闲链表 + * Empty link list */ list _free; /** * 空闲链元素个数 + * number of the elements in the empty link */ volatile size_t _free_size; /** * 链接 + * Connection */ list_data *_vConn; /** * 超时链表 + * Timeout link list */ multimap _tl; /** * 上次检查超时时间 + * Last timeout time */ time_t _lastTimeoutTime; /** * 链接ID的魔数 + * Magic Number of Link IDs */ uint32_t _iConnectionMagic; }; @@ -1425,42 +1756,50 @@ public: public: /** * 构造函数 + * Constructor */ NetThread(TC_EpollServer *epollServer, int index); /** * 析构函数 + * Destructor */ virtual ~NetThread(); /** * 获取网络线程的index + * Get the index for the network threads * @return */ int getIndex() const { return _threadIndex; } /** * 网络线程执行函数 + * Network thread execution function */ virtual void run(); /** * 停止网络线程 + * Stop the network thread */ void terminate(); /** * 生成epoll + * Generate epoll */ void createEpoll(uint32_t maxAllConn); /** * 初始化udp监听 + * Initialize UDP listening */ void initUdp(const unordered_map &listeners); /** * 是否服务结束了 + * Whether the service is end. * * @return bool */ @@ -1468,23 +1807,28 @@ public: /** * 获取Epoller对象 + * Get the Epoller Object + * * @return TC_Epoller* */ TC_Epoller* getEpoller() { return &_epoller; } /** * 唤醒网络线程 + * Wake up the network thread */ void notify(); /** * 关闭连接 + * Close Connection * @param uid */ void close(const shared_ptr &data); /** * 发送数据 + * Send data * @param uid * @param s */ @@ -1492,6 +1836,7 @@ public: /** * 获取某一监听端口的连接数 + * Get the number of connections for a listening port * @param lfd * * @return vector @@ -1500,6 +1845,7 @@ public: /** * 获取连接数 + * Get the number of connections * * @return size_t */ @@ -1507,54 +1853,63 @@ public: /** * 记录日志 + * Logging * @param s */ void debug(const string &s) const; /** * INFO日志 + * INFO LOG * @param s */ void info(const string &s) const; /** * TARS日志 + * TARS LOG * @param s */ void tars(const string &s) const; /** * 记录错误日志 + * Log errors * @param s */ void error(const string &s) const; /** * 是否启用防止空链接攻击的机制 + * Whether the mechanism to prevent null link attacks is enabled. * @param bEnable */ void enAntiEmptyConnAttack(bool bEnable); /** *设置空连接超时时间 + *Set empty connection timeout */ void setEmptyConnTimeout(int timeout); /** *设置udp的接收缓存区大小,单位是B,最小值为8192,最大值为DEFAULT_RECV_BUFFERSIZE + *Sets the size of the receiving buffer in UDP in B, with a minimum of 8192 and a maximum of DEFAULT_RECV_BUFFERSIZE */ void setUdpRecvBufferSize(size_t nSize=DEFAULT_RECV_BUFFERSIZE); - /** - * 发送队列的大小 - * @return size_t - */ - size_t getSendRspSize(); +// /** +// * 发送队列的大小 +// * Size of sending queue +// * @return size_t +// */ +// size_t getSendRspSize(); protected: /** * 获取连接 + * Get connection * @param id * * @return ConnectionPtr @@ -1563,6 +1918,7 @@ public: /** * 添加tcp链接 + * Add TCP connection * @param cPtr * @param iIndex */ @@ -1570,6 +1926,7 @@ public: /** * 添加udp连接 + * Add UDP connection * @param cPtr * @param index */ @@ -1577,29 +1934,36 @@ public: /** * 删除链接 + * Delete connection * @param cPtr * @param bEraseList 是否是超时连接的删除 + * @param bEraseList Whether it is deletion of timeout connection * @param closeType 关闭类型,0:表示客户端主动关闭;1:服务端主动关闭;2:连接超时服务端主动关闭 + * @param closeType Close type, 0: indicates active closure of client, 1: active closure of server, 2: active closure of connection timeout server */ void delConnection(Connection *cPtr, bool bEraseList = true, EM_CLOSE_T closeType=EM_CLIENT_CLOSE); /** * 处理管道消息 + * Processing Pipeline Messages */ void processPipe(); /** * 处理网络请求 + * Processing Network Request */ void processNet(const epoll_event &ev); /** * 空连接超时时间 + * Empty connection timeout */ int getEmptyConnTimeout() const; /** *是否空连接检测 + *Empty connection detection examination */ bool isEmptyConnCheck() const; @@ -1610,16 +1974,19 @@ public: private: /** * 服务 + * Service */ TC_EpollServer *_epollServer; /** * net线程的id + * the net thread id */ std::thread::id _threadId; /** * 线程索引 + * the thread index */ int _threadIndex; @@ -1630,26 +1997,31 @@ public: /** * 停止 + * Stop */ bool _bTerminate; /** * 通知epoll + * Notify epoll */ TC_Epoller::NotifyInfo _notify; /** * 管理的连接链表 + * Managed Link List */ ConnectionList _list; /** * 发送队列 + * Sending Queue */ send_queue _sbuffer; /** *空连接检测机制开关 + *Switch for empty connection detection mechanism */ bool _bEmptyConnAttackCheck; @@ -1657,16 +2029,20 @@ public: /** * 空连接超时时间,单位是毫秒,默认值2s, * 该时间必须小于等于adapter自身的超时时间 + * Empty connection timeout in milliseconds, default 2s, + * The time must be less than or equal to the adapter's own timeout */ int _iEmptyCheckTimeout; /** * udp连接时接收包缓存大小,针对所有udp接收缓存有效 + * Received packet cache size on UDP connection, valid for all UDP receive caches */ size_t _nUdpRecvBufferSize; /** * 通知信号 + * Notification signal */ bool _notifySignal = false; }; @@ -1674,77 +2050,91 @@ public: public: /** * 构造函数 + * Constructor */ TC_EpollServer(unsigned int iNetThreadNum = 1); /** * 析构函数 + * Destructor */ ~TC_EpollServer(); /** * 是否启用防止空链接攻击的机制 + * Whether mechanisms to prevent empty link attacks are enabled * @param bEnable */ void enAntiEmptyConnAttack(bool bEnable); /** *设置空连接超时时间 + *Set empty connection timeout */ void setEmptyConnTimeout(int timeout); /** * 设置本地日志 + * Set local log * @param plocalLogger */ void setLocalLogger(RollWrapperInterface *pLocalLogger) { _pLocalLogger = pLocalLogger; } /** * 选择网络线程 + * Select network threads * @param fd */ inline NetThread* getNetThreadOfFd(int fd) { return _netThreads[fd % _netThreads.size()]; } /** * 合并handle线程和网络线程 + * Merge handle and network threads * @param merge */ void setMergeHandleNetThread(bool merge) { _mergeHandleNetThread = merge; } /** * 是否合并handle线程网络线程 + * Whether to merge handle thread network threads * @return */ inline bool isMergeHandleNetThread() const { return _mergeHandleNetThread; } /** * 绑定监听socket + * Bind listening socket * @param ls */ int bind(BindAdapterPtr &lsPtr); /** * 启动业务处理线程 + * Start Business Processing Thread */ void startHandle(); /** * 生成epoll + * Generate epoll */ void createEpoll(); /** * 运行 + * Run */ void waitForShutdown(); /** * 停止服务 + * Stop Service */ void terminate(); /** * 是否服务结束了 + * Whether the service is over * * @return bool */ @@ -1752,6 +2142,7 @@ public: /** * 根据名称获取BindAdapter + * Get BindAdapter according to the name * @param sName * @return BindAdapterPtr */ @@ -1759,23 +2150,27 @@ public: /** * 获取所有adatapters + * Get all adapters * @return */ vector getBindAdapters(); /** * 向网络线程添加连接 + * Add remote connection to the network thread */ void addConnection(Connection * cPtr, int fd, CONN_TYPE iType); /** * 关闭连接 + * Close connection * @param uid */ void close(const shared_ptr &data); /** * 发送数据 + * Send data * @param uid * @param s */ @@ -1783,6 +2178,7 @@ public: /** * 获取某一监听端口的连接数 + * Get the connection amount of a certain listening port * @param lfd * * @return vector @@ -1791,6 +2187,7 @@ public: /** * 获取监听socket信息 + * Get the information of the listening socket * * @return map */ @@ -1798,6 +2195,7 @@ public: /** * 获取所有连接的数目 + * Get the amount of all connections * * @return size_t */ @@ -1805,62 +2203,74 @@ public: /** * 记录日志 + * Logging * @param s */ void debug(const string &s) const; /** * INFO日志 + * INFO LOG * @param s */ void info(const string &s) const; /** * 记录错误日志 + * Log errors * @param s */ void error(const string &s) const; /** * tars日志 + * tars log * @param s */ void tars(const string &s) const; /** * 获取网络线程的数目 + * Get the amount of the network threads */ unsigned int getNetThreadNum() { return _netThreadNum; } /** * 获取网络线程的指针集合 + * Get the collection of pointers for a network thread */ vector getNetThread() { return _netThreads; } /** * 停止线程 + * Stop the thread */ void stopThread(); /** * 获取所有业务线程的数目 + * Get the amount of all the bussiness threads */ size_t getLogicThreadNum(); //回调给应用服务 + //Callback to application service typedef std::function application_callback_functor; /** * 设置waitForShutdown线程回调的心跳 + * Set the heartbeat of the thread callback of the waitForShutdown * @param hf [description] */ void setCallbackFunctor(const application_callback_functor &hf) { _hf = hf; } //网络线程发送心跳的函数 + //Function for network threads to send heartbeats typedef std::function heartbeat_callback_functor; /** * 设置netthread网络线程发送心跳的函数 + * Function for setting netthreaded network threads to send heartbeats * @param hf [description] */ void setHeartBeatFunctor(const heartbeat_callback_functor& heartFunc) { _heartFunc = heartFunc; } @@ -1872,6 +2282,7 @@ protected: /** * 接收句柄 + * Receiving handle * @param fd * @return */ @@ -1879,6 +2290,7 @@ protected: /** * 绑定端口 + * Bind Port * @param ep * @param s * @param manualListen @@ -1889,11 +2301,13 @@ protected: private: /** * 网络线程 + * Network Thread */ std::vector _netThreads; /* * 网络线程数目 + * Network Thread Amount */ unsigned int _netThreadNum; @@ -1904,26 +2318,31 @@ private: /** * 通知epoll + * Notify epoll */ TC_Epoller::NotifyInfo _notify; /* * 服务是否停止 + * Whether the service is stopped */ bool _bTerminate; /* * 业务线程是否启动 + * Whether the bussiness thread is started. */ bool _handleStarted; /** * 合并网络和业务线程 + * Merge network and business threads */ bool _mergeHandleNetThread = false; /** * 本地循环日志 + * Local Loop Log */ RollWrapperInterface *_pLocalLogger; @@ -1934,16 +2353,19 @@ private: /** * 监听socket + * Listening socket */ unordered_map _listeners; /** * 应用回调 + * Application callback */ application_callback_functor _hf; /** * 发送心跳的函数 + * Heartbeat Sending Function */ heartbeat_callback_functor _heartFunc; diff --git a/util/include/util/tc_epoller.h b/util/include/util/tc_epoller.h index 8fda42a39f3b65afd26032f3e85be55b917da87e..143d03e99c60247967bb833b248d3be42277ef76 100755 --- a/util/include/util/tc_epoller.h +++ b/util/include/util/tc_epoller.h @@ -40,11 +40,13 @@ namespace tars /** * @file tc_epoller.h * @brief epoll操作封装类 + * @brief Epoll operation encapsulation class */ ///////////////////////////////////////////////// /** * @brief epoll异常类 +* @brief epoll exception class */ struct TC_Epoller_Exception : public TC_Exception { @@ -54,12 +56,14 @@ struct TC_Epoller_Exception : public TC_Exception /** * @brief epoller操作类,已经默认采用了EPOLLET方式做触发 + * @brief epoller operation class, EPOLLET has been used by default for triggering */ class TC_Epoller { public: /** * @brief 通知epoll从wait中醒过来 + * @brief Notice epoll to wake up from 'wait' */ class NotifyInfo { @@ -69,31 +73,37 @@ public: /** * 初始化 + * Initialization */ void init(TC_Epoller *ep); /** * 添加关联数据 + * Add corresponding data */ void add(uint64_t data); /** * 通知notify醒过来 + * Notice notify to wake up */ void notify(); /** * 释放掉 + * Diposit */ void release(); /** * 获取通知fd + * Get notifyFd */ int notifyFd(); /** * 清除通知, 否则会一直响应 + * Clear up notice, otherwise, it will always respond */ // void clear(); protected: @@ -103,26 +113,32 @@ public: // bool _clear = true; TC_Epoller *_ep; + /*Events associated with the notification handle*/ uint64_t _data; //关联到通知句柄的事件 }; /** * @brief 构造函数. + * @brief Constructor Function * * @param bEt 默认是ET模式,当状态发生变化的时候才获得通知 + * @param bEt The default is et mode, which is notified when the status changes */ TC_Epoller(); /** * @brief 析够函数. + * @brief Destructor */ ~TC_Epoller(); /** * @brief 生成epoll句柄. + * @brief Generate epoll handle. * * @param max_connections epoll服务需要支持的最大连接数 + * @param max_connections Maximum number of connections the epoll service needs to support */ void create(int max_connections); @@ -135,49 +151,66 @@ public: /** * @brief 添加监听句柄. + * @brief Add listening handle. * * @param fd 句柄 + * @param fd handle * @param data 辅助的数据, 可以后续在epoll_event中获取到 + * @param data auxiliary data that can be obtained in epoll_event subsequently * @param event 需要监听的事件EPOLLIN|EPOLLOUT + * @param event Events to be listened on EPOLLIN|EPOLLOUT * */ void add(SOCKET_TYPE fd, uint64_t data, int32_t event); /** * @brief 修改句柄事件. + * @brief Modify handle event * * @param fd 句柄 + * @param fd handle * @param data 辅助的数据, 可以后续在epoll_event中获取到 + * @param data auxiliary data that can be obtained in epoll_event subsequently * @param event 需要监听的事件EPOLLIN|EPOLLOUT + * @param event Events to be listened on EPOLLIN|EPOLLOUT */ void mod(SOCKET_TYPE fd, uint64_t data, int32_t event); /** * @brief 删除句柄事件. + * @brief Delete handle event. * * @param fd 句柄 + * @param fd handle * @param data 辅助的数据, 可以后续在epoll_event中获取到 + * @param data auxiliary data that can be obtained in epoll_event subsequently * @param event 需要监听的事件EPOLLIN|EPOLLOUT + * @param event Events to be listened on EPOLLIN|EPOLLOUT */ void del(SOCKET_TYPE fd, uint64_t data, int32_t event); /** * @brief 等待时间. + * @brief wait time * * @param millsecond 毫秒 * @return int 有事件触发的句柄数 + * @return int Number of handles triggered by events */ int wait(int millsecond); /** * @brief 获取被触发的事件. + * @brief Get the triggered handle * * @return struct epoll_event&被触发的事件 + * @return Struct epoll_event& triggered event */ epoll_event& get(int i);// { assert(_pevs != 0); return _pevs[i]; } /** * @brief 是否有读事件 + * @brief whether it have event to read * * @return */ @@ -185,6 +218,7 @@ public: /** * @brief 是否有写事件 + * @brief whether it have event to write * * @return */ @@ -192,6 +226,7 @@ public: /** * @brief 是否有异常事件 + * @brief whether it have eception event * * @return */ @@ -199,13 +234,16 @@ public: /** * @brief 获取低位/高位数据 + * @brief Get low/high bit data * @param high: true:高位, false:低位 + * @param high: true:high level, false:low level * @return */ static uint32_t getU32(const epoll_event &ev, bool high); /** * @brief 获取64bit数据 + * @brief Get 64 bit data * @return */ static uint64_t getU64(const epoll_event &ev); @@ -214,12 +252,19 @@ protected: /** * @brief 控制epoll,将EPOLL设为边缘触发EPOLLET模式 + * @brief Control epoll, set EPOLL to Edge Trigger EPOLLET mode * @param fd 句柄,在create函数时被赋值 + * @param fd Handle, assigned when creating function * @param data 辅助的数据, 可以后续在epoll_event中获取到 + * @param data auxiliary data that can be obtained in epoll_event subsequently * @param event 需要监听的事件 + * @param event the event to be listened * @param op EPOLL_CTL_ADD: 注册新的fd到epfd中; * EPOLL_CTL_MOD:修改已经注册的fd的监听事件; * EPOLL_CTL_DEL:从epfd中删除一个fd; + * @param op EPOLL_CTL_ADD:Register new FD into EPFD + * EPOLL_CTL_MOD:Modify the monitoring events for registered fd + * EPOLL_CTL_DEL:Delete an FD from epfd * */ void ctrl(SOCKET_TYPE fd, uint64_t data, uint32_t events, int op); @@ -237,11 +282,13 @@ protected: /** * 最大连接数 + * The max amount of connections */ int _max_connections; /** * 事件集 + * Event Set */ epoll_event *_pevs; }; diff --git a/util/include/util/tc_ex.h b/util/include/util/tc_ex.h index 075b84e18e6fee6bef594477f9ef0b9189056304..6015697a93b3a58bc5a0e9f6c367e0bead4730da 100644 --- a/util/include/util/tc_ex.h +++ b/util/include/util/tc_ex.h @@ -28,40 +28,52 @@ namespace tars /** * @file tc_ex.h * @brief 异常类 +* @brief Exception Class */ ///////////////////////////////////////////////// /** * @brief 异常类. +* @brief Exception Class */ class TC_Exception : public exception { public: /** * @brief 构造函数,提供了一个可以传入errno的构造函数 + * @brief Constructor , provide a constructor which can pass errno * @param err, 是否附带系统错误信息(linux版本, 用errno获取错误码, windows版本, 用GetLastError()获取错误) + * @param err Whether system error information is included(linux: use errno to get error code, windows: use GetLastError() to get errors) * * @param buffer 异常的告警信息 + * @param buffer alert information of exceptions */ explicit TC_Exception(const string &buffer); /** - * @brief 构造函数,提供了一个可以传入errno的构造函数, + * @brief 构造函数,提供了一个可以传入errno的构造函数, + * @brief Constructor , provider a constructor to pass errno * * 异常抛出时直接获取的错误信息 + * get error message directly when throw exception * - * @param buffer 异常的告警信息 + * @param buffer 异常的告警信息 + * @param buffer alert information of exceptions + * * @param errno 传入:errno, windows版本 传入:GetLastError() + * @param errno pass:errno, windows version pass:GetLastError() */ TC_Exception(const string &buffer, int err); /** * @brief 析够数函 + * @brief Destructor */ virtual ~TC_Exception() throw(); /** * @brief 错误信息. + * @brief Error Message * * @return const char* */ @@ -69,22 +81,28 @@ public: /** * @brief 获取错误码 + * @brief Get error code * * @return 成功获取返回0 + * @return if get successfully , return 0 */ int getErrCode() { return _code; } /** * @brief 获取错误字符串(linux是errno, windows是GetLastError()) + * @brief Get the error string (linux: errno, windows: GetLastError()) * * @return 成功获取返回0 + * @return if get successfully , return 0 */ static string parseError(int err); /** * @brief 获取系统错误码(linux是errno, windows是GetLastError) + * @brief Get system error code(linux: errno, windows: GetLastError()) * * @return 成功获取返回0 + * @return if get successfully , return 0 */ static int getSystemCode(); @@ -95,20 +113,24 @@ private: /** * 错误码 + * Error Code */ int _code; /** * 异常的相关信息 + * Information about exceptions */ string _buffer; }; //为了避免windows平台GetLastError()获取不对的问题, 因为抛异常, throw TC_Exception("xxxx", TC_Exception::getSystemCode())时 +//In order to avoid getting the wrong getlasterror() on Windows platform, throw TC_ Exception("xxxx", TC_ Exception:: getsystemcode()) //回调用系统函数分配内存, 导致错误码被改写, 因此专门定义宏来抛出异常 +//Callback uses system function to allocate memory, which causes error code to be rewritten, so it specially defines macro to throw exception //先获取到错误码, 再throw -#define TARS_THROW_EXCEPTION(EX_CLASS, buffer) throw EX_CLASS(buffer) -#define TARS_THROW_EXCEPTION_SYSCODE(EX_CLASS, buffer) \ +//Get the error code first, and then throw +#define THROW_EXCEPTION_SYSCODE(EX_CLASS, buffer) \ { \ int ret = TC_Exception::getSystemCode(); \ throw EX_CLASS(buffer, ret); \ diff --git a/util/include/util/tc_fifo.h b/util/include/util/tc_fifo.h index 0a35f4e5f593edd0c6a07e468b9e52eef6157ec9..b6967eebdbf8fa15f982ede8d884ef4e87cd6644 100644 --- a/util/include/util/tc_fifo.h +++ b/util/include/util/tc_fifo.h @@ -29,11 +29,13 @@ namespace tars /** *@file tc_fifo.h *@brief FIFO封装类. + *@brief FIFO encapsulation class */ ///////////////////////////////////////////////// /** *@brief 管道操作类. + *@brief Pipeline operation. */ class TC_Fifo { @@ -42,6 +44,8 @@ public: /** * @brief 管道操作的枚举类型. * 定义了对管道的操作类型,EM_WRITE:写管道,EM_READ :读管道 + * @brief Enumeration types for pipeline operations + * Defines the type of operation on the pipeline, EM_ Write: write pipe, EM_ Read: read pipe */ enum ENUM_RW_SET { @@ -52,75 +56,99 @@ public: public: /** * @brief 构造函数. + * @brief Constructor * * @param bOwener : 是否拥有管道,默认为ture + * @param bOwener : Whether the pipeline is owned, the default is ture */ TC_Fifo(bool bOwener = true); /** * @brief 析构函数. + * @brief Constructor */ ~TC_Fifo(); public: /** * @brief 打开FIFO. + * @brief Open FIFO * * @param sPath 要打开的FIFO文件的路径 + * @param sPath the file path of the FIFO to open * @param enRW 管道操作类型 + * @param enRN Pipe opration type * @param mode 该FIFO文件的权限 ,默认为可读可写 + * @param mode The permissions of this FIFO file are read-write by default * @return 0-成功,-1-失败 + * @return 0 - successfull, -1 - failed */ int open(const std::string & sPath, ENUM_RW_SET enRW, mode_t mode = 0777); /** * @brief 关闭fifo + * @brief Close FIFO */ void close(); /** * @brief 获取FIFO的文件描述符. + * @brief Get the file descriptor of FIFO * * @return FIFO的文件描述符 + * @return the file descriptor of FIFO */ int fd() const { return _fd; } /** * @brief 读数据, 当读取成功时,返回实际读取的字节数,如果返回的值是0,代表已经读到文件的结束;小于0表示出现了错误 + * @brief read data, when read successfully, return the actual number of bytes read, if the value returned is 0, the end of the file has been read; less than 0 indicates an error * @param buffer 读取的内容 + * @param buffer the content to be read * @param max_size 读取数据的大小 + * @param max_size size of the data to be read * @return 读到的数据长度 ,小于0则表示失败 + * @return the length of the read data , if it is less then 0, read failed */ int read(char * szBuff, const size_t sizeMax); /** * @brief 向管道写数据. + * @brief Write data to the pipeline * * @param szBuff 要写入的数据 + * @param szBuff data to be wrote * @param sizeBuffLen 数据的大小 + * @param sizeBuffLen size of data * @return 大于0:表示写了部分或者全部数据 * 小于0:表示出现错误 + * @return geater than 0: Some or all of the data are shown and written + * less than 0: Error */ int write(const char * szBuff, const size_t sizeBuffLen); private: /** * FIFO文件的路径 + * file path of FIFO */ std::string _sPathName; /** * 是否拥有FIFO + * whether it have FIFO */ bool _bOwner; /** * FIFO的文件的操作类型 + * file opration type of FIFO */ ENUM_RW_SET _enRW; /** * FIFO的文件描述符 + * file descriptor of FIFO */ int _fd; }; diff --git a/util/include/util/tc_file_mutex.h b/util/include/util/tc_file_mutex.h index e45efed6a8bf270ac4e4c083bd063816f7eac3aa..e1b2320963fa868eed8fe940edb7eb4c6c8aa9ed 100644 --- a/util/include/util/tc_file_mutex.h +++ b/util/include/util/tc_file_mutex.h @@ -46,6 +46,7 @@ struct TC_FileMutex_Exception : public TC_Lock_Exception /** * @brief 文件锁, 注意:只能在进程间加锁. + * @brief file lock , attion : You can only lock between processes */ class TC_FileMutex { @@ -53,45 +54,56 @@ public: /** * @brief 构造函数. + * @brief Constructor */ TC_FileMutex(); /** * @brief 析够函数. + * @brief Desturctor */ virtual ~TC_FileMutex(); /** * @brief 初始化文件锁. + * @brief Initialize file lock * * @param filename 欲操作的文件的名字 + * @param filename file name of the file to be operated */ void init(const std::string& filename); /** * @brief 加读锁. + * @brief Add read lock * *@return 0-成功加锁,-1-加锁失败 + *@return 0 - lock successfully, -1 - failed to lock */ int rlock(); /** * @brief 解读锁. + * @brief Unlock * * @return 0-成功解锁,-1-解锁失败 + * @return 0 - unlock successfully, -1 - failed to unlock */ int unrlock(); /** * @brief 尝试读锁. + * @brief Try read lock. * * @throws TC_FileMutex_Exception - * @return 加锁成功则返回false, 否则返回false + * @return 加锁成功则返回true, 否则返回false + * @return return true: lock successfully, return false: failed to lock */ bool tryrlock(); /** * @brief 加写锁. + * @brief Add write lock * * @return int */ @@ -99,60 +111,83 @@ public: /** * @brief 解写锁. + * @brief Unlock */ int unwlock(); /** * @brief 尝试写锁. + * @brief Try write lock. * - * @return bool,加锁成功则返回false, 否则返回false + * @return bool,加锁成功则返回true, 否则返回false + * @return return true: lock successfully, return false: failed to lock * @throws TC_FileMutex_Exception */ bool trywlock(); /** * @brief 写锁. + * @brief Read Lock. * * @return int, 0 正确 + * @return int, 0 - correct */ int lock(){return wlock();}; /** * @brief 解写锁. + * @brief Unlock */ int unlock(); /** * @brief 尝试解锁. + * @brief Try unlock * * @throws TC_FileMutex_Exception * @return int, 0 正确 + * @return int, 0 - correct */ bool trylock() {return trywlock();}; protected: /** * @brief 设置锁. + * @brief Set a lock. * * @param fd 欲设置的文件描述词 + * @param fd the file descriptor of the lock to be set * @param cmd 欲操作的指令 + * @param cmd opeational order * @param type 三种状态,分别为F_RDLCK ,F_WRLCK ,F_UNLCK + * @param type three states: F_RDLCK ,F_WRLCK ,F_UNLCK * @param offset 偏移量 + * @param offset the offset * @param whence 锁定的起始位置,三种方式 + * @param whence the starting position pf the lock,three ways * @param len 锁定区域的大小 + * @param len the size of the locked area * @return int:成功则返回0,若有错误则返回-1. + * @return int: successfully,return 0; else return -1 */ int lock(int fd, int cmd, int type, off_t offset, int whence, off_t len); /** * @brief 是否被其他进程锁了. + * @brief Whether it is locked by other threads * * @param fd 欲设置的文件描述词 + * @param fd the file desciptor to be set * @param type 三种状态,分别为F_RDLCK ,F_WRLCK ,F_UNLCK + * @param type three types: F_RDLCK ,F_WRLCK ,F_UNLCK * @param offset 偏移量 + * @param offset the offset * @param whence 锁定的起始位置,三种方式 + * @param whence the starting position of the lock ,three ways * @param len 锁定区域的大小 - * @return bool 有所返回true,无锁返回false. + * @param len the size of the locked area + * @return bool 有所返回true,无锁返回false. + * @return int: successfully,return 0; else return -1 */ bool hasLock(int fd, int type, off_t offset, int whence, off_t len); diff --git a/util/include/util/tc_http.h b/util/include/util/tc_http.h index 5adb5626d062cf6d758623b196fce52ae66f6193..507718ae6184329d9ae9c427c3080bb886d89cc3 100755 --- a/util/include/util/tc_http.h +++ b/util/include/util/tc_http.h @@ -25,6 +25,7 @@ #include "util/tc_socket.h" #include "util/tc_epoller.h" #include "util/tc_timeout_queue.h" +#include "util/tc_network_buffer.h" #include #include #include @@ -60,6 +61,7 @@ namespace tars */ ///////////////////////////////////////////////// +class TC_NetWorkBuffer; /** * @brief http协议解析异常类 @@ -341,6 +343,9 @@ protected: class TC_Http { public: + static unordered_map HEADER; + static unordered_map HEADER_REVERSE; + /** * @brief 构造函数 */ @@ -560,10 +565,25 @@ public: string getHeader(const string& sHeader) const; /** - * @brief 获取http头部map. - * - * @return http_header_type& + * 是否有header + * @param sHeader + * @return */ + bool hasHeader(const char *sHeader) const; + + /** + * @brief 检查头部 + * @param sHeader + * @param value + * @return + */ + bool checkHeader(const char *sHeader, const char *value) const; + + /** + * @brief 获取http头部map. + * + * @return http_header_type& + */ const http_header_type& getHeaders() const{return _headers;} /** @@ -578,43 +598,87 @@ public: void reset(); /** - * @brief 读取一行. - * - * @param ppChar 读取位置指针 - * @return string 读取的内容 - */ - static string getLine(const char** ppChar); - - /** - * @brief 读取一行. - * - * @param ppChar 读取位置指针 - * @param iBufLen 长度 - * @return string 读取的内容 - */ - static string getLine(const char** ppChar, int iBufLen); - - /** - * @brief 生成头部字符串(不包含第一行). + * @brief 生成头部字符串(不包含第一行), 直接累加到sHttpHeader后 * * @return string:头部字符串 */ - string genHeader() const; + void genHeader(string &sHttpHeader) const; /** - * @brief 该http原始数据包是否是chunk编码格式. - * - * @return bool:包含返回true,否则返回false + * @brief 生成头部字符串(不包含第一行) + * @return */ + string genHeader() const; + + /** + * @brief 该http原始数据包是否是chunk编码格式. + * + * @return bool:包含返回true,否则返回false + */ bool isChunked() const { return _bIsChunked; } /** * @brief 解析请求head,不解析第一行, * 第一行请求包和响应包不一样, 后面的数据解析为map格式 - * @param szBuffer + * @param szBuffer * @return const char*, 偏移的指针 */ - static const char* parseHeader(const char* szBuffer, http_header_type &sHeader); +// static const char* parseHeader(const char* szBuffer, http_header_type &sHeader); +// +// template +// static void parseHeader(const ForwardIterator1 &beginIt, const ForwardIterator2 &headerIt, http_header_type &sHeader) +// { +// sHeader.clear(); +// +// string sep = "\r\n"; +// string colon = ":"; +// +// bool first = true; +// auto lineStartIt= beginIt; +// +// while (true) +// { +// auto it = std::search(lineStartIt, headerIt, sep.c_str(), sep.c_str() + sep.size()); +// if(it == headerIt) +// { +// break; +// } +// +// //first line ignore +// if(!first) +// { +// auto itF = std::search(lineStartIt, it, colon.c_str(), colon.c_str() + colon.size()); +// if (itF != it) +// { +// string name; +// name.resize(itF - lineStartIt); +// std::copy(lineStartIt, itF, name.begin()); +// +// string value; +// value.resize(it - (itF + 1)); +// std::copy(itF + 1, it, value.begin()); +// +// sHeader.insert(multimap::value_type(TC_Common::trim(name, " "), +// TC_Common::trim(value, " "))); +// +// } +// } +// else +// { +// first = false; +// } +// +// lineStartIt = it + sep.size(); +// } +// } + + /** + * 解析, 尽量避免内存copy, 提升效率 + * @param beginIt + * @param headerIt + * @param sHeader + */ + static size_t parseHeaderString(const char *beginIt, const char *headerIt, http_header_type &sHeader); protected: @@ -628,6 +692,11 @@ protected: */ size_t _headLength; + /** + * 获取版本 + */ + string _version; + /** * http头部内容 */ @@ -815,7 +884,7 @@ public: * false:还需要继续解析,如果服务器主动关闭连接的模式下 * , 也可能不需要再解析了 */ - bool incrementDecode(string &sBuffer); + bool incrementDecode(TC_NetWorkBuffer &buff); /** * @brief 解析http应答(采用string方式) , @@ -950,19 +1019,69 @@ public: /** * @brief 解析应答头. - * + * * @param szBuffer 应答头信息 * @return */ - void parseResponseHeader(const char* szBuffer); +// /** +// * +// * @param szBuffer +// */ +// template +// void parseResponseHeader(const ForwardIterator1 &beginIt, const ForwardIterator2 &headerIt) +// { +// string line = "\r\n"; +// +// auto it = std::search(beginIt, headerIt, line.c_str(), line.c_str() + line.size()); +// +// assert(it != headerIt); +// +// string sep = " "; +// +// auto f1 = std::search(beginIt, headerIt, sep.c_str(), sep.c_str() + sep.size()); +// if(f1 == headerIt) +// { +// throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response parse version format error : " + string(beginIt, it)); +// } +// +// auto f2 = std::search(f1 + 1, headerIt, sep.c_str(), sep.c_str() + sep.size()); +// if(f1 == headerIt) +// { +// throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response parse status format error : " + string(beginIt, it)); +// } +// +// _headerLine = string(beginIt, it); +// +// if(TC_Port::strncasecmp(_headerLine.c_str(), "HTTP/", 5) != 0) +// { +// throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response version is not start with 'HTTP/' : " + _headerLine); +// } +// +// _version = string(beginIt, f1); +// +// _status = TC_Common::strto(string(f1 + 1, f2)); +// +// _about = TC_Common::trim(string(f2 + 1, it)); +// +// parseHeader(beginIt, headerIt, _headers); +// } + + size_t parseResponseHeaderString(const char *beginIt, const char *headerIt); protected: /** - * 添加内容, 增量解析用到 + * 添加内容 * @param sBuffer */ void addContent(const string &sBuffer); + /** + * 添加内容 + * @param buffer + * @param length + */ + void addContent(const char *buffer, size_t length); + protected: /** @@ -975,11 +1094,6 @@ protected: */ string _about; - /** - * 获取版本 - */ - string _version; - /** * 获取第一行 */ @@ -1022,11 +1136,12 @@ public: REQUEST_PUT, REQUEST_DELETE, REQUEST_PATCH, + REQUEST_PRI, }; /** * @brief 检查http请求是否收全. - * + * * @param sBuffer http请求 * @throws TC_HttpRequest_Exception, 不支持的http协议, 抛出异常 * @return true: 收全, false:不全 @@ -1034,6 +1149,13 @@ public: static bool checkRequest(const char* sBuffer, size_t len); /** + * 检查http包是否收全 + * @param buff + * @return + */ + static bool checkRequest(TC_NetWorkBuffer &buff); + + /** * @brief 重置 */ void reset(); @@ -1068,7 +1190,16 @@ public: */ bool decode(const string &sBuffer); - /** + /** + * @brief 解析http请求, 如果不是HTTP请求则抛出异常. + * + * @param sBuffer 要解析的http请求 + * @return sBuffer是否是完整的http请求 + * @throw TC_HttpRequest_Exception + */ + bool decode(const vector &sBuffer); + + /** * @brief 解析http请求, * 如果不是HTTP请求则抛出异常(采用vector方式). * @@ -1095,6 +1226,12 @@ public: void encode(vector &buffer); /** + * encode buffer to TC_NetWorkBuffer + * @param buff + */ + void encode(TC_NetWorkBuffer &buff); + + /** * @brief 设置请求包. * * @param sUrl 例如:http://www.qq.com/query?a=b&c=d @@ -1196,6 +1333,12 @@ public: */ void setRequestType(int requestType) { _requestType = requestType ; } + /** + * get method + * @return + */ + const string &getMethod() const; + /** * set method * @param @@ -1255,17 +1398,16 @@ public: * @return 是delete请求返回true,否则返回false */ bool isDELETE() const { return _requestType == REQUEST_DELETE; } - /** * @brief 获取请求的URL. - * + * * @return const TC_URL& */ const TC_URL &getURL() const { return _httpURL; } /** * @brief 获取完整的http请求. - * + * * @return http请求串 */ string getOriginRequest() const { return _httpURL.getURL(); } @@ -1281,7 +1423,7 @@ public: * @brief 获取http请求的url部分, 即?前面,不包括Host, * 例如http://www.qq.com/abc?a=b#def, 则为:/abc * @return http请求的url部分 - * */ + * */ string getRequestUrl() const { return _httpURL.getPath(); } /** @@ -1293,30 +1435,30 @@ public: /** * @brief 解析请求头部. - * + * * @param szBuffer 请求头部 - * @return size_t + * @return */ - size_t parseRequestHeader(const char* szBuffer); + void parseRequestHeader(const char* szBuffer, const char *header); - /** - * @brief 请求类型到字符串. - * - * @param iRequestType 请求 - * @return 解析后的字符串 - */ - string requestType2str(int iRequestType) const; +// /** +// * @brief 请求类型到字符串. +// * +// * @param iRequestType 请求 +// * @return 解析后的字符串 +// */ +// const char *requestType2str(int iRequestType) const; protected: /** * @brief 对http请求编码. - * + * * @param sUrl 需要进行编码的http请求 * @param iRequestType 编码后的输出流 * @return void */ - void encode(int iRequestType, ostream &os); +// void encode(int iRequestType, ostream &os); /** * @brief 解析URL diff --git a/util/include/util/tc_http2.h b/util/include/util/tc_http2.h index c465fd174f96161c601fe1572a3d395ebaad7fc8..0aacd56929c63be77c0e9bc1a4af8306a735124d 100644 --- a/util/include/util/tc_http2.h +++ b/util/include/util/tc_http2.h @@ -198,11 +198,12 @@ public: * @param buff * @return */ - int submit(const string &method, const string &path, const map &header, const vector &buff); +// int submit(const string &method, const string &path, const map &header, const vector &buff); + int submit(const TC_HttpRequest &request); - /** - * @brief response - */ + /** + * @brief response + */ std::unordered_map> &responses() { return _responses; } /** diff --git a/util/include/util/tc_http_async.h b/util/include/util/tc_http_async.h index d6b5ce0d3ce26567c5e8695d28e0aca93fa529d7..c20c51f4362f0cbcaed08103b1ca9f1eb5886ecf 100644 --- a/util/include/util/tc_http_async.h +++ b/util/include/util/tc_http_async.h @@ -20,6 +20,7 @@ #include #include "util/tc_platform.h" #include "util/tc_thread_pool.h" +#include "util/tc_network_buffer.h" #include "util/tc_http.h" #include "util/tc_autoptr.h" #include "util/tc_socket.h" @@ -42,17 +43,6 @@ namespace tars */ ///////////////////////////////////////////////// - -///** -//* @brief 线程异常 -//*/ -//struct TC_HttpAsync_Exception : public TC_Exception -//{ -// TC_HttpAsync_Exception(const string &buffer) : TC_Exception(buffer) {}; -// TC_HttpAsync_Exception(const string &buffer, int err) : TC_Exception(buffer, err) {}; -// ~TC_HttpAsync_Exception() throw() {}; -//}; - /** * @brief 异步线程处理类. */ @@ -128,6 +118,15 @@ protected: */ AsyncRequest(TC_HttpRequest &stHttpRequest, RequestCallbackPtr &callbackPtr, bool bUseProxy); + /** + * @brief 构造. + * + * @param stHttpRequest + * @param callbackPtr + * @param addr + */ + AsyncRequest(TC_HttpRequest &stHttpRequest, RequestCallbackPtr &callbackPtr, const string &addr); + /** * @brief 析构 */ @@ -140,11 +139,6 @@ protected: */ int getfd() const { return _fd.getfd(); } - /** - * 获取通知fd - */ - // int getNotifyfd() const { return _notify.getfd(); } - /** * @brief 发起建立连接. * @@ -155,7 +149,7 @@ protected: * @brief 获取系统错误提示 * @return */ - string getError(const char* sDefault) const; + string getError(const string &sDefault) const; /** * @brief 发生异常 @@ -266,8 +260,8 @@ protected: string _sHost; uint32_t _iPort; uint32_t _iUniqId; - string _sReq; - string _sRsp; + TC_NetWorkBuffer _sendBuffer; + TC_NetWorkBuffer _recvBuffer; RequestCallbackPtr _callbackPtr; bool _bindAddrSet; struct sockaddr _bindAddr; @@ -300,6 +294,15 @@ public: */ void doAsyncRequest(TC_HttpRequest &stHttpRequest, RequestCallbackPtr &callbackPtr, bool bUseProxy = false); + /** + * @brief 异步发起请求. + * + * @param stHttpRequest + * @param httpCallbackPtr + * @param addr, 请求地址, ip:port + */ + void doAsyncRequest(TC_HttpRequest &stHttpRequest, RequestCallbackPtr &callbackPtr, const string &addr); + /** * @brief 设置proxy地址 * @@ -373,11 +376,6 @@ protected: */ static void timeout(AsyncRequestPtr& ptr); - /** - * @brief 具体网络处理 - */ - // static void process(AsyncRequestPtr &p, int events); - /** * @brief 确保线程 * @param _threadId [description] diff --git a/util/include/util/tc_json.h b/util/include/util/tc_json.h old mode 100644 new mode 100755 index 4f42550ad386e22f8a5bc9ea77730abedd680da4..ea34539fa24d29850f57ef1f1a99fe8626df8158 --- a/util/include/util/tc_json.h +++ b/util/include/util/tc_json.h @@ -107,6 +107,20 @@ public: { return eJsonTypeObj; } + const JsonValuePtr &get(const char *name) + { + auto it = value.find(name); + + if(it == value.end()) + { + char s[64]; + snprintf(s, sizeof(s), "get obj error(key is not exists)[key:%s]", name); + throw TC_Json_Exception(s); + } + + return it->second; + } + virtual ~JsonValueObj(){} public: unordered_map value; @@ -123,7 +137,7 @@ public: { return eJsonTypeArray; } - void push_back(JsonValuePtr & p) + void push_back(const JsonValuePtr & p) { value.push_back(p); } @@ -242,9 +256,11 @@ public: //json类型到字符串的转换 static string writeValue(const JsonValuePtr & p); static void writeValue(const JsonValuePtr & p, string& ostr); + static void writeValue(const JsonValuePtr & p, vector& buf); //json字符串到json结构的转换 static JsonValuePtr getValue(const string & str); + static JsonValuePtr getValue(const vector& buf); private: //string 类型到json字符串 static void writeString(const JsonValueStringPtr & p, string& ostr); diff --git a/util/include/util/tc_logger.h b/util/include/util/tc_logger.h index 4d7aaa54a26f0f9c332683b28001449ad85c1f83..2237bc8eb34e5c108074cd9189929558a11aea67 100644 --- a/util/include/util/tc_logger.h +++ b/util/include/util/tc_logger.h @@ -134,7 +134,8 @@ namespace tars /** * @brief 具体写日志基类 */ - class TC_LoggerRoll : public TC_HandleBase + + class UTIL_DLL_API TC_LoggerRoll : public TC_HandleBase { public: /** @@ -1231,7 +1232,7 @@ namespace tars //抛异常前继续进入_t 以便打远程日志 _t(_of, buffer); - TARS_THROW_EXCEPTION_SYSCODE(TC_Logger_Exception, "[TC_RollBySize::roll]:fopen fail: " + sLogFileName); + THROW_EXCEPTION_SYSCODE(TC_Logger_Exception, "[TC_RollBySize::roll]:fopen fail: " + sLogFileName); // throw TC_Logger_Exception("[TC_RollBySize::roll]:fopen fail: " + sLogFileName, TC_Exception::getSystemCode()); } } @@ -1281,7 +1282,7 @@ namespace tars _of.open(sLogFileName.c_str(), ios::app); if (!_of) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Logger_Exception, "[TC_RollBySize::roll]:fopen fail: " + sLogFileName); + THROW_EXCEPTION_SYSCODE(TC_Logger_Exception, "[TC_RollBySize::roll]:fopen fail: " + sLogFileName); // throw TC_Logger_Exception("[TC_RollBySize::roll]:fopen fail: " + sLogFileName, TC_Exception::getSystemCode()); } } @@ -1329,16 +1330,16 @@ namespace tars /** * @brief 根据时间滚动日志分隔类型 */ - class TarsLogType : public TC_HandleBase + class LogType : public TC_HandleBase { public: - TarsLogType() : _next_time_t(0), _format("%Y%m%d"), _frequency(1), _des("day") + LogType() : _next_time_t(0), _format("%Y%m%d"), _frequency(1), _des("day") { _next_time_t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); _next_cut_time = TC_Common::tm2str(_next_time_t, "%Y%m%d"); } - virtual ~TarsLogType() {} + virtual ~LogType() {} //频率值 virtual size_t frequence() = 0; @@ -1391,15 +1392,15 @@ namespace tars size_t _frequency; string _des; }; - typedef TC_AutoPtr TarsLogTypePtr; + typedef TC_AutoPtr LogTypePtr; - class TarsLogByDay : public TarsLogType + class LogByDay : public LogType { public: static const string FORMAT; public: - explicit TarsLogByDay(const string &format = "%Y%m%d", size_t frequency = 1) + explicit LogByDay(const string &format = "%Y%m%d", size_t frequency = 1) { init(format, frequency); _des = TC_Common::tostr(_frequency) + "day"; @@ -1411,13 +1412,13 @@ namespace tars } }; - class TarsLogByHour : public TarsLogType + class LogByHour : public LogType { public: static const string FORMAT; public: - explicit TarsLogByHour(const string &format = "%Y%m%d%H", size_t frequency = 1) + explicit LogByHour(const string &format = "%Y%m%d%H", size_t frequency = 1) { init(format, frequency); _des = TC_Common::tostr(_frequency) + "hour"; @@ -1430,13 +1431,13 @@ namespace tars } }; - class TarsLogByMinute : public TarsLogType + class LogByMinute : public LogType { public: static const string FORMAT; public: - explicit TarsLogByMinute(const string &format = "%Y%m%d%H%M", size_t frequency = 1) + explicit LogByMinute(const string &format = "%Y%m%d%H%M", size_t frequency = 1) { init(format, frequency); _des = TC_Common::tostr(_frequency) + "minute"; @@ -1470,10 +1471,10 @@ namespace tars * @param format,日志文件记录格式,按天,小时,分钟 * @param bHasSufix,日志文件是否添加".log"后缀 * @param sConcatstr,日志路径和时间字串之间的连接符,例如:app_log/test_20121210.log - * @param logTypePtr,日志记录类型,详见TarsLogType + * @param logTypePtr,日志记录类型,详见LogType * @param bIsRemote,是否是远程日志实例 */ - void init(const string &path, const string &format = "%Y%m%d", bool bHasSufix = true, const string &sConcatstr = "_", const TarsLogTypePtr &logTypePtr = NULL, bool bIsRemote = false) + void init(const string &path, const string &format = "%Y%m%d", bool bHasSufix = true, const string &sConcatstr = "_", const LogTypePtr &logTypePtr = NULL, bool bIsRemote = false) { this->_roll->init(path, format, bHasSufix, sConcatstr, logTypePtr, bIsRemote); } @@ -1539,7 +1540,7 @@ namespace tars * @param bIsRemote */ - void init(const string &path, const string &format = "%Y%m%d", bool bHasSufix = true, const string &sConcatstr = "_", const TarsLogTypePtr &logTypePtr = NULL, bool bIsRemote = false) + void init(const string &path, const string &format = "%Y%m%d", bool bHasSufix = true, const string &sConcatstr = "_", const LogTypePtr &logTypePtr = NULL, bool bIsRemote = false) { std::lock_guard lock(*this); @@ -1692,7 +1693,7 @@ namespace tars { //抛异常前继续进入_t 以便打远程日志 _t(_of, buffer); - TARS_THROW_EXCEPTION_SYSCODE(TC_Logger_Exception, "[TC_RollByTime::roll]:fopen fail: " + sLogFileName); + THROW_EXCEPTION_SYSCODE(TC_Logger_Exception, "[TC_RollByTime::roll]:fopen fail: " + sLogFileName); // throw TC_Logger_Exception("[TC_RollByTime::roll]:fopen fail: " + sLogFileName, TC_Exception::getSystemCode()); } } @@ -1744,7 +1745,7 @@ namespace tars * 按天/小时/分钟输出日志时的记录类型 */ - TarsLogTypePtr _logTypePtr; + LogTypePtr _logTypePtr; /** * 是否是远程日志实例 */ diff --git a/util/include/util/tc_network_buffer.h b/util/include/util/tc_network_buffer.h index 474dfd8fd1bc1bdc96ee74dcce9d62695f1445cf..d8904a98eb3166bd84adc57cd81484c59f3f4191 100755 --- a/util/include/util/tc_network_buffer.h +++ b/util/include/util/tc_network_buffer.h @@ -29,6 +29,15 @@ namespace tars { +/** +* @brief +*/ +struct TC_NetWorkBuffer_Exception : public TC_Exception +{ + TC_NetWorkBuffer_Exception(const string &sBuffer) : TC_Exception(sBuffer){}; + ~TC_NetWorkBuffer_Exception() {}; +}; + class TC_NetWorkBuffer { public: @@ -109,7 +118,21 @@ public: size_t pos() const { return _pos; } - void add(uint32_t ret) + char &at(size_t offset) + { + if(_pos + offset >= _buffer.size() ) + throw TC_NetWorkBuffer_Exception("[TC_NetWorkBuffer::Buffer] at '" + TC_Common::tostr(offset) + "' offset overflow"); + return _buffer[_pos + offset]; + } + + char at(size_t offset) const + { + if(_pos + offset >= _buffer.size() ) + throw TC_NetWorkBuffer_Exception("[TC_NetWorkBuffer::Buffer] at '" + TC_Common::tostr(offset) + "' offset overflow"); + return _buffer[_pos + offset]; + } + + void add(uint32_t ret) { _pos += ret; assert(_pos <= _buffer.size()); @@ -121,6 +144,212 @@ public: }; + typedef std::list>::const_iterator buffer_list_iterator; + + class buffer_iterator : public std::iterator + { + public: + buffer_iterator(const TC_NetWorkBuffer *buffer, size_t offset) : _buffer(buffer) + { + parseOffset(offset); + } + + /** + * @brief copy + * @param it + */ + buffer_iterator(const buffer_iterator &it) + { + if(this != &it) + { + _buffer = it._buffer; + _pos = it._pos; + _offset = it._offset; + _it = it._it; + } + } + + /** + * + * @param mcmi + * + * @return bool + */ + bool operator==(const buffer_iterator& it) const + { + if (_buffer == it._buffer && _it == it._it && _offset == it._offset) + { + return true; + } + + return false; + } + + /** + * + * @param mv + * + * @return bool + */ + bool operator!=(const buffer_iterator& it) const + { + if (_buffer == it._buffer && _it == it._it && _offset == it._offset) + { + return false; + } + + return true; + } + + char & operator *() + { + return (*_it)->buffer()[_pos]; + } + + char * operator ->() + { + return &(*_it)->buffer()[_pos]; + } + + char& operator *() const + { + return (*_it)->buffer()[_pos]; + } + + const char* operator ->() const + { + return &(*_it)->buffer()[_pos]; + } + + buffer_iterator operator +(size_t n) const + { + return buffer_iterator(_buffer, _offset + n); + } + + buffer_iterator operator += (size_t n) + { + parseOffset(_offset + n); + return *this; + } + + difference_type operator -(const buffer_iterator &n) const + { + return _offset - n._offset; + } + + buffer_iterator operator -(size_t n) const + { + return buffer_iterator(_buffer, _offset - n); + } + + bool operator < (const buffer_iterator n) const + { + return _offset (const buffer_iterator n) const + { + return _offset>n._offset; + } + + bool operator >= (const buffer_iterator n) const + { + return _offset>=n._offset; + } + + //前置++ + buffer_iterator& operator ++() + { + if(_offset >= _buffer->getBufferLength()) + return *this; + + assert(_it != _buffer->_bufferList.end()); + + if(_pos < (*_it)->length() - 1) + { + ++_pos; + ++_offset; + } + else + { + ++_it; + ++_offset; + _pos = 0; + } + return *this; + } + + //后置++ + buffer_iterator operator ++(int) + { + buffer_iterator it(*this); + + if(_it != _buffer->_bufferList.end()) + { + if (_pos < (*_it)->length() - 1) + { + ++_pos; + ++_offset; + } + else + { + ++_it; + ++_offset; + _pos = 0; + } + } + else + { + _offset = _buffer->getBufferLength(); + _pos = 0; + } + return it; + } + + protected: + void parseOffset(size_t offset) + { + _offset = offset; + + bool flag = false; + for(auto it = _buffer->_bufferList.begin(); it != _buffer->_bufferList.end(); ++it) + { + if(offset >= (*it)->length()) + { + offset -= (*it)->length(); + } + else + { + _it = it; + _pos = offset; + flag = true; + + break; + } + } + + if(!flag) + { + _offset = _buffer->getBufferLength(); + _pos = 0; + _it = _buffer->_bufferList.end(); + } + } + + friend class TC_NetWorkBuffer; + + protected: + const TC_NetWorkBuffer* _buffer; + buffer_list_iterator _it; + size_t _offset = 0; + size_t _pos = 0; + }; + /** * 必须以connection来构造(不同服务模型中获取的对象不一样, 需要自己强制转换) * @param buff @@ -139,11 +368,17 @@ public: } } - /** - * 获取connection, 不同服务模型中获取的对象不一样, 需要自己强制转换 - * @param buff - */ - void* getConnection() { return _connection; } + /** + * 获取connection, 不同服务模型中获取的对象不一样, 需要自己强制转换 + * @param buff + */ + void* getConnection() { return _connection; } + + /** + * 获取connection, 不同服务模型中获取的对象不一样, 需要自己强制转换 + * @param buff + */ + void setConnection(void *connection) { _connection = connection; } /** * 设置上下文数据, 可以业务存放数据 @@ -169,6 +404,12 @@ public: */ void addBuffer(const std::vector& buff); + /** + * 增加buffer + * @param buff + */ + void addBuffer(const std::string& buff); + /** * 增加buffer * @param buff @@ -177,6 +418,75 @@ public: void addBuffer(const char* buff, size_t length); /** + * begin + * @return + */ + buffer_iterator begin() const; + + /** + * end + * @return + */ + buffer_iterator end() const; + + /** + * 查找 + * @param str + * @param length + * @return + */ + buffer_iterator find(const char *str, size_t length); + + /** + * 获取从开头到迭代器(前一个, 不包括迭代器本身)所有buffer + * T: string or vector + * @param it + * @return + */ + template + T iteratorToIterator(const buffer_iterator &sit, const buffer_iterator &eit) + { + T buff; + + if(sit == end() || sit == eit) + { + return buff; + } + + if(sit > eit) + { + throw TC_NetWorkBuffer_Exception("[TC_NetWorkBuffer::iteratorToIterator] sit > eit error"); + } + + buff.resize(eit - sit); + + std::copy(sit, eit, buff.begin()); + + return buff; + } + + /** + * 匹配到对应buff, 获取之前的buffer + * T: string or vector + * @param sep + * @param length + * @return + */ + template + T getPrefixBuffer(const char *sep, size_t length) + { + T buff; + auto sit = std::search(begin(), end(), sep, sep + length); + + if(sit == end()) + { + return buff; + } + + return iteratorToIterator(begin(), sit); + } + + /** * 清空所有buffer */ void clearBuffers(); @@ -192,6 +502,12 @@ public: */ size_t getBufferLength() const; + /** + * buffer list length + * @return + */ + size_t size() const { return _bufferList.size(); } + /** * 获取第一块有效数据buffer的指针, 可以用来发送数据 * @return @@ -230,6 +546,34 @@ public: */ bool getHeader(size_t len, std::vector &buffer) const; + /** + * 读取len字节的buffer(避免len个字节被分割到多个buffer的情况)(注意: 不往后移动) + * getHeader(10), getHeader>(10); + * @param len + * @return 不够会抛异常TC_NetWorkBuffer_Exception + */ + template + T getHeader(size_t len) const + { + if(getBufferLength() < len) + { + throw TC_NetWorkBuffer_Exception("[TC_NetWorkBuffer::getHeader] no enough buff(" + TC_Common::tostr(getBufferLength()) + ") to get(" + TC_Common::tostr(len) + ")"); + } + + T buffer; + + if(len == 0) + { + return buffer; + } + + buffer.resize(len); + + getBuffers(&buffer[0], len); + + return buffer; + } + /** * 往后移动len个字节 * @param len diff --git a/util/include/util/tc_openssl.h b/util/include/util/tc_openssl.h index 367829ac8ac96d0c376962a2023bb864dba31c56..ba48097b8c8c7231b347b7e5179d343557f6ffc0 100644 --- a/util/include/util/tc_openssl.h +++ b/util/include/util/tc_openssl.h @@ -77,7 +77,7 @@ public: * @param verifyClient * @return */ - static shared_ptr newCtx(const std::string& cafile, const std::string& certfile, const std::string& keyfile, bool verifyClient); + static shared_ptr newCtx(const std::string& cafile, const std::string& certfile, const std::string& keyfile, bool verifyClient, const string &ciphers); /** * new ssl diff --git a/util/include/util/tc_platform.h b/util/include/util/tc_platform.h index 5e3445443e3bd6564982e4bf5cb4af433adbea29..3ff48dc72547569d21bd12c7e6497f7f451c3e3c 100644 --- a/util/include/util/tc_platform.h +++ b/util/include/util/tc_platform.h @@ -43,4 +43,43 @@ #include #endif + +//UTIL 动态库编译的导入和导出 +#if TARGET_PLATFORM_WINDOWS + +#ifdef UTIL_DLL_EXPORT +#define UTIL_DLL_API __declspec(dllexport) +#else + +#ifdef UTIL_USE_DLL +#define UTIL_DLL_API __declspec(dllimport) +#else +#define UTIL_DLL_API +#endif + +#endif + +#else +#define UTIL_DLL_API +#endif + +//servant 动态库编译的导入和导出 +#if TARGET_PLATFORM_WINDOWS + +#ifdef SVT_DLL_EXPORT +#define SVT_DLL_API __declspec(dllexport) +#else + +#ifdef SVT_USE_DLL +#define SVT_DLL_API __declspec(dllimport) +#else +#define SVT_DLL_API +#endif + +#endif + +#else +#define SVT_DLL_API +#endif + #endif diff --git a/util/include/util/tc_port.h b/util/include/util/tc_port.h index 4500ac7b000c16d7b23c47f649fc395c597617a5..8e8414d323d8e8427d28ebb94773d0bce27e28af 100755 --- a/util/include/util/tc_port.h +++ b/util/include/util/tc_port.h @@ -31,8 +31,11 @@ namespace tars class TC_Port { public: + static int strcmp(const char *s1, const char *s2); - static int strcasecmp(const char *s1, const char *s2); + static int strncmp(const char *s1, const char *s2, size_t n); + + static int strcasecmp(const char *s1, const char *s2); static int strncasecmp(const char *s1, const char *s2, size_t n); @@ -62,6 +65,12 @@ public: static int closeSocket(int fd); static int64_t getpid(); + + static std::string getEnv(const std::string &name); + + static void setEnv(const std::string &name, const std::string &value); + + static std::string exec(const char* cmd); }; } diff --git a/util/include/util/tc_singleton.h b/util/include/util/tc_singleton.h index 615b852224e54d8027808d68ae3adea3b4569f4d..ac8436d3d12d5657b138bc4216e0f93bb54ef447 100644 --- a/util/include/util/tc_singleton.h +++ b/util/include/util/tc_singleton.h @@ -163,9 +163,35 @@ public: } }; +template +class CreateRealStatic +{ +public: + /** + * @brief 创建. + * + * @return T* + */ + static T* create() + { + static T t; + return &t; + } + + /** + * @brief 释放. + * + * @param t + */ + static void destroy(T *t) + { + } +}; + //////////////////////////////////////////////////////////////// /** * @brief 定义LifetimePolicy:定义对象的声明周期管理 + * 进程退出时销毁对象 */ template class DefaultLifetime @@ -182,6 +208,12 @@ public: } }; +/** + * @brief, + * 对象被销毁后可以重生(比如log,全局任何时候都需要) + * + * @author jarod (7/29/2015) + */ template class PhoneixLifetime { @@ -202,10 +234,15 @@ private: template bool PhoneixLifetime::_bDestroyedOnce = false; -template -struct NoDestroyLifetime -{ - static void scheduleDestruction(T*, void (*)()) +/** + * @brief 不做对象销毁 + * + * @author jarod (7/29/2015) + */ +template +struct NoDestroyLifetime +{ + static void scheduleDestruction(T*, void (*)()) { } @@ -237,56 +274,54 @@ public: */ static T *getInstance() { - //加锁, 双check机制, 保证正确和效率 - if(!_pInstance) - { - TC_ThreadLock::Lock lock(_tl); - if(!_pInstance) - { - if(_destroyed) + static std::mutex __mutex_singleton; + + auto sin= __pInstance.load(); + if ( !sin ){ + std::lock_guard myLock(__mutex_singleton); + sin= __pInstance.load(); + if( !sin ){ + if(__destroyed) { LifetimePolicy::deadReference(); - _destroyed = false; + __destroyed = false; } - _pInstance = CreatePolicy::create(); - LifetimePolicy::scheduleDestruction((T*)_pInstance, &destroySingleton); + + sin = CreatePolicy::create(); + __pInstance.store(sin); + LifetimePolicy::scheduleDestruction(__pInstance, &destroySingleton); } } - - return (T*)_pInstance; + + return sin; } - -protected: + virtual ~TC_Singleton(){}; + +protected: static void destroySingleton() { - assert(!_destroyed); - CreatePolicy::destroy((T*)_pInstance); - _pInstance = NULL; - _destroyed = true; + assert(!__destroyed); + CreatePolicy::destroy((T*)__pInstance); + __pInstance = NULL; + __destroyed = true; } protected: - static TC_ThreadLock _tl; - static volatile T* _pInstance; - static bool _destroyed; + static atomic __pInstance; + static bool __destroyed; protected: - TC_Singleton(){} - virtual ~TC_Singleton(){}; - TC_Singleton (const TC_Singleton &); - TC_Singleton &operator=(const TC_Singleton &); + TC_Singleton() = default; + TC_Singleton (const TC_Singleton &) = default; + TC_Singleton &operator=(const TC_Singleton &) = default; }; -template class CreatePolicy, template class LifetimePolicy> -TC_ThreadLock TC_Singleton::_tl; - -template class CreatePolicy, template class LifetimePolicy> -bool TC_Singleton::_destroyed = false; - -template class CreatePolicy, template class LifetimePolicy> -volatile T* TC_Singleton::_pInstance = NULL; +template class CreatePolicy, template class LifetimePolicy> +bool TC_Singleton::__destroyed = false; +template class CreatePolicy, template class LifetimePolicy> +atomic TC_Singleton::__pInstance = {nullptr}; } #endif diff --git a/util/include/util/tc_spin_lock.h b/util/include/util/tc_spin_lock.h index 1bb3ec3927cdb19d08a8ccd944001b552d84dc6a..a2f9d29f4a5f99d4dbefb8222d55231ea18c1d7e 100755 --- a/util/include/util/tc_spin_lock.h +++ b/util/include/util/tc_spin_lock.h @@ -2,6 +2,7 @@ #ifndef __TC_SPIN_LOCK_H #define __TC_SPIN_LOCK_H +#include "util/tc_platform.h" #include #include @@ -15,7 +16,7 @@ namespace tars * 不能阻塞wait, 只能快速加解锁, 适用于锁粒度非常小的情况, 减小线程切换的开销 * 不支持trylock */ -class TC_SpinLock +class UTIL_DLL_API TC_SpinLock { public: diff --git a/util/include/util/tc_thread_mutex.h b/util/include/util/tc_thread_mutex.h index 53711ff26fcaeb9ccf99a137cd5c2d1659c1e46f..e95913e2c54e3b7bcd382adf8ba0157f2b0701d7 100644 --- a/util/include/util/tc_thread_mutex.h +++ b/util/include/util/tc_thread_mutex.h @@ -18,6 +18,7 @@ #define __TC_THREAD_MUTEX_H #include "util/tc_lock.h" +#include "util/tc_platform.h" #include #include @@ -41,7 +42,7 @@ class TC_ThreadCond; * * 通常不直接使用,和TC_Monitor配合使用,即TC_ThreadLock; */ -class TC_ThreadMutex +class UTIL_DLL_API TC_ThreadMutex { public: @@ -68,8 +69,8 @@ public: protected: // noncopyable - TC_ThreadMutex(const TC_ThreadMutex&); - void operator=(const TC_ThreadMutex&); + TC_ThreadMutex(const TC_ThreadMutex&) = delete; + void operator=(const TC_ThreadMutex&) = delete; friend class TC_ThreadCond; @@ -82,7 +83,7 @@ protected: * * 采用线程库实现 **/ -class TC_ThreadRecMutex +class UTIL_DLL_API TC_ThreadRecMutex { public: diff --git a/util/include/util/tc_thread_pool.h b/util/include/util/tc_thread_pool.h index d584acc021dca005f34e59c73bca36e2b655970c..2d56217f0191d2615ad36c3ed6887e01430ea814 100644 --- a/util/include/util/tc_thread_pool.h +++ b/util/include/util/tc_thread_pool.h @@ -20,6 +20,7 @@ #include "util/tc_platform.h" #include "util/tc_thread.h" #include +#include #include #include #include diff --git a/util/include/util/tc_thread_queue.h b/util/include/util/tc_thread_queue.h index 907271265929be17d392ee1737c18a0a8b70ed81..edfc7d629dd8dfa42c52c9aca649e1ac4da3fcd8 100644 --- a/util/include/util/tc_thread_queue.h +++ b/util/include/util/tc_thread_queue.h @@ -48,6 +48,14 @@ public: typedef D queue_type; + /** + * @brief 从头部获取数据, 没有数据抛异常 + * + * @param t + * @return bool: true, 获取了数据, false, 无数据 + */ + T front(); + /** * @brief 从头部获取数据, 没有数据则等待. * @@ -60,6 +68,13 @@ public: */ bool pop_front(T& t, size_t millsecond = 0, bool wait = true); + /** + * @brief 从头部获取数据. + * + * @return bool: true, 获取了数据, false, 无数据 + */ + bool pop_front(); + /** * @brief 通知等待在队列上面的线程都醒过来 */ @@ -148,6 +163,13 @@ protected: mutable std::mutex _mutex; }; +template T TC_ThreadQueue::front() +{ + std::unique_lock lock(_mutex); + + return _queue.front(); +} + template bool TC_ThreadQueue::pop_front(T& t, size_t millsecond, bool wait) { if(wait) { @@ -198,6 +220,21 @@ template bool TC_ThreadQueue::pop_front(T& t, size } +template bool TC_ThreadQueue::pop_front() +{ + std::unique_lock lock(_mutex); + if (_queue.empty()) + { + return false; + } + + _queue.pop_front(); + assert(_size > 0); + --_size; + + return true; +} + template void TC_ThreadQueue::notifyT() { std::unique_lock lock(_mutex); diff --git a/util/include/util/tc_thread_rwlock.h b/util/include/util/tc_thread_rwlock.h index 2a6d6e57bd4f9dbff3456eaad76d0e6b2e90913c..3f5a48beb2ae75d1993309db4d17c3181f2f902f 100644 --- a/util/include/util/tc_thread_rwlock.h +++ b/util/include/util/tc_thread_rwlock.h @@ -20,6 +20,7 @@ #include #include #include "util/tc_lock.h" +#include "util/tc_platform.h" #include using namespace std; @@ -36,7 +37,7 @@ namespace tars ///////////////////////////////////////////////// -class TC_ThreadRWLocker +class UTIL_DLL_API TC_ThreadRWLocker { protected: diff --git a/util/include/util/tc_timeout_queue_new.h b/util/include/util/tc_timeout_queue_new.h index 684f834628a8538631767f42ae24dab978f5e1af..6d5f7753a395d9b49ee2001a1d2b6286b891551a 100644 --- a/util/include/util/tc_timeout_queue_new.h +++ b/util/include/util/tc_timeout_queue_new.h @@ -17,9 +17,10 @@ #ifndef __TC_TIMEOUT_QUEUE_NEW_H #define __TC_TIMEOUT_QUEUE_NEW_H -#include #include #include +#include +// #include #include #include #include @@ -53,7 +54,7 @@ public: typedef multimap time_type; typedef list send_type; - using data_functor = std::function; + typedef std::function data_functor; struct PtrInfo { diff --git a/util/include/util/tc_timeout_queue_noid.h b/util/include/util/tc_timeout_queue_noid.h index 2a735250831b31ccd86c008bb57640c794c6cb7e..cf21276fcf8601aae17cd072ec80e9e6196b2a83 100644 --- a/util/include/util/tc_timeout_queue_noid.h +++ b/util/include/util/tc_timeout_queue_noid.h @@ -69,6 +69,10 @@ public: { } + typename list_type::iterator begin() { return _list.begin(); } + typename list_type::iterator end() { return _list.end(); } + + /** * @brief 取出队列第一个数据 * diff --git a/util/include/util/tc_timeprovider.h b/util/include/util/tc_timeprovider.h index 6163a93e56e5447f2c6df3aeaeeb56ae9169fdfd..5b6992439dde126d5333032ad65955ddb7876815 100644 --- a/util/include/util/tc_timeprovider.h +++ b/util/include/util/tc_timeprovider.h @@ -42,7 +42,7 @@ class TC_TimeProvider; /** * @brief 提供秒级别的时间 */ -class TC_TimeProvider +class UTIL_DLL_API TC_TimeProvider { public: diff --git a/util/include/util/tc_xml.h b/util/include/util/tc_xml.h new file mode 100755 index 0000000000000000000000000000000000000000..00a8a24219b91fb85881e64c13358b8300f619b7 --- /dev/null +++ b/util/include/util/tc_xml.h @@ -0,0 +1,226 @@ +#ifndef __TC_XML_H_ +#define __TC_XML_H_ + +#include +#include +#include +#include +#include + +#include + +#include "util/tc_autoptr.h" +using namespace std; + +namespace tars +{ +///////////////////////////////////////////////// +// 说明: Xml编解码的公共库 +// Author : linfengchen@tencent.com +///////////////////////////////////////////////// + +/** +* 编解码抛出的异常 +*/ +struct TC_Xml_Exception : public TC_Exception +{ + TC_Xml_Exception(const string &buffer) : TC_Exception(buffer){}; + TC_Xml_Exception(const string &buffer, int err) : TC_Exception(buffer, err){}; + ~TC_Xml_Exception() throw(){}; +}; + +enum eXmlType +{ + eXmlTypeString = 1, + eXmlTypeArray, + eXmlTypeObj, +}; + +/* + * Xml类型的基类。没有任何意义 + */ +class XmlValue : public tars::TC_HandleBase +{ +public: + virtual eXmlType getType()=0; + virtual ~XmlValue(){} +protected: + XmlValue* parent; +}; +typedef tars::TC_AutoPtr XmlValuePtr; + + +/* + * Xml类型 string类型 + */ +class XmlValueString : public XmlValue +{ +public: + XmlValueString(const string & s, bool _cdata = false):value(s), cdata(_cdata) + { + } + XmlValueString(bool _cdata = false):cdata(_cdata) + { + } + + eXmlType getType() + { + return eXmlTypeString; + } + virtual ~XmlValueString(){} + string value; + bool cdata; +}; +typedef tars::TC_AutoPtr XmlValueStringPtr; + + +/* + * Xml类型 object类型 例如 + */ +class XmlValueObj: public XmlValue +{ +public: + eXmlType getType() + { + return eXmlTypeObj; + } + virtual ~XmlValueObj(){} +public: + map value; +}; +typedef tars::TC_AutoPtr XmlValueObjPtr; + +/* + * Xml类型 array类型 例如 + */ +class XmlValueArray: public XmlValue +{ +public: + eXmlType getType() + { + return eXmlTypeArray; + } + void push_back(XmlValuePtr & p) + { + value.push_back(p); + } + virtual ~XmlValueArray(){} +public: + vector value; +}; +typedef tars::TC_AutoPtr XmlValueArrayPtr; + +/* + * 分析Xml字符串用到的 读字符的类 + */ +class BufferXmlReader +{ +public: + const char * _buf; ///< 缓冲区 + size_t _len; ///< 缓冲区长度 + size_t _pos; ///< 当前位置 + +public: + + BufferXmlReader () :_buf(NULL),_len(0), _pos(0) {} + + void reset() { _pos = 0;} + + void setBuffer(const char * buf, size_t len) + { + _buf = buf; + _len = len; + _pos = 0; + } + + void setBuffer(const std::vector &buf) + { + _buf = &buf[0]; + _len = buf.size(); + _pos = 0; + } + + bool hasEnd() + { + return (_pos >= _len || *(_buf + _pos) == 0); + } + + bool expect(char ch) + { + if (get() == ch) + { + _pos++; + return true; + } + return false; + } + + void skip(size_t i = 1) + { + _pos += i; + } + + char read() + { + check(++_pos); + return *(_buf+_pos-1); + } + + char get(size_t pos = 0) + { + check(pos + _pos); + return *(_buf+_pos + pos); + } + + size_t pos() + { + return _pos; + } + + void check(size_t pos) + { + if (pos > _len) + { + char s[64]; + snprintf(s, sizeof(s), "buffer[%u] overflow when peekBuf, over %u.", (uint32_t)pos, (uint32_t)_len); + throw TC_Xml_Exception(s); + } + } +}; + +/* + * 分析Xml的类。都是static + */ +class TC_Xml +{ +public: + //Xml类型到字符串的转换 + static string writeValue(const XmlValuePtr& p, bool bHead = true); + static void writeValue(const XmlValuePtr& p, vector& buf, bool bHead = true); + //Xml字符串到Xml结构的转换 + static XmlValuePtr getValue(const string& str); + static XmlValuePtr getValue(const vector& buf); +private: + static XmlValuePtr getNode(BufferXmlReader& reader, const string& nodename = ""); + static XmlValueStringPtr getValue(BufferXmlReader& reader); + static XmlValueStringPtr getCdata(BufferXmlReader& reader); + + static void insertArray(const string& name, XmlValuePtr& v, XmlValueObjPtr& p); + static bool isEndNode(BufferXmlReader& reader, const string& nodename); + static void ignoreDeclaration(BufferXmlReader& reader); + static bool ignoreComment(BufferXmlReader& reader); + + + static void writeArray(std::ostream& os, const string& name, const XmlValuePtr& p); + static void writeString(std::ostream& os, const XmlValuePtr& p); + static void writeEChar(std::ostream& os, const string& data); + static void writeObj(std::ostream& os, const XmlValuePtr& p); + + //判断一个字符是否符合Xml定义的空白字符 + static bool isspace(char c); +}; + +} + +#endif + diff --git a/util/src/CMakeLists.txt b/util/src/CMakeLists.txt index e27e3a49771ce5cfef07dad603dcd8c55a16daca..091af25d2e48ed3fc7b1399ddca95a786769accc 100644 --- a/util/src/CMakeLists.txt +++ b/util/src/CMakeLists.txt @@ -1,6 +1,7 @@ set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) IF(WIN32) +include_directories(epoll_windows) aux_source_directory(epoll_windows/src. DIR_SRCS) ENDIF() diff --git a/util/src/tc_cgi.cpp b/util/src/tc_cgi.cpp index 1698b35520724988b9132a788ee7d593e16aaec1..997f64642c2dc6e1cfd65de818ec67ba8fa88836 100644 --- a/util/src/tc_cgi.cpp +++ b/util/src/tc_cgi.cpp @@ -371,7 +371,7 @@ bool TC_Cgi::writeFile(FILE*fp, const string &sFileName, const string &sBuffer, if(ret != (int)sBuffer.length()) { fclose(fp); - throw TC_Cgi_Exception("[TC_Cgi::parseFormData] upload file '" + _mpUpload[sFileName]._sServerFileName + "' error:" + string(strerror(errno))); + throw TC_Cgi_Exception("[TC_Cgi::parseFormData] upload file '" + _mpUpload[sFileName]._sServerFileName + "' error", TC_Exception::getSystemCode()); } iTotalWrite += sBuffer.length(); _mpUpload[sFileName]._iSize = iTotalWrite; @@ -438,7 +438,8 @@ void TC_Cgi::parseFormData(multimap &mmpParams, const string &sB if ( (fp = fopen(sUploadFileName.c_str(),"w")) == NULL) { mmpParams.clear(); //clear , exception safe - throw TC_Cgi_Exception("[TC_Cgi::parseFormData] Upload File '" + sValue + "' to '" + sUploadFileName +"' error! " + string(strerror(errno))); + THROW_EXCEPTION_SYSCODE(TC_Cgi_Exception, "[TC_Cgi::parseFormData] Upload File '" + sValue + "' to '" + sUploadFileName +"' error"); + // throw TC_Cgi_Exception("[TC_Cgi::parseFormData] Upload File '" + sValue + "' to '" + sUploadFileName +"' error! " + string(strerror(errno))); } } else diff --git a/util/src/tc_config.cpp b/util/src/tc_config.cpp index 8e526afcdd965f865db015b317d2a5d560c41c7a..c1cc06a214b42955ea28f8e58afa8b4ce4cd8b6f 100644 --- a/util/src/tc_config.cpp +++ b/util/src/tc_config.cpp @@ -383,7 +383,7 @@ string TC_ConfigDomain::tostr(int i) const string sTab; for(int k = 0; k < i; ++k) { - sTab += "\t"; + sTab += " "; } ostringstream buf; @@ -399,11 +399,11 @@ string TC_ConfigDomain::tostr(int i) const //值为空, 则不打印出= if(it->second.empty()) { - buf << "\t" << sTab << reverse_parse(_key[n]) << endl; + buf << " " << sTab << reverse_parse(_key[n]) << endl; } else { - buf << "\t" << sTab << reverse_parse(_key[n]) << "=" << reverse_parse(it->second) << endl; + buf << " " << sTab << reverse_parse(_key[n]) << "=" << reverse_parse(it->second) << endl; } } @@ -525,7 +525,8 @@ void TC_Config::parseFile(const string &sFileName) ff.open(sFileName.c_str()); if (!ff) { - throw TC_Config_Exception("[TC_Config::parseFile]:fopen fail: " + sFileName, errno); + THROW_EXCEPTION_SYSCODE(TC_Config_Exception, "[TC_Config::parseFile]:fopen fail: " + sFileName); + // throw TC_Config_Exception("[TC_Config::parseFile]:fopen fail: " + sFileName, TC_Exception::getSystemCode()); } parse(ff); diff --git a/util/src/tc_des.cpp b/util/src/tc_des.cpp index d15a99698c906ef9584473b90e60cc4d0f0f1021..dc662138a51283159e51dcadde41531789e98501 100644 --- a/util/src/tc_des.cpp +++ b/util/src/tc_des.cpp @@ -560,7 +560,10 @@ string TC_Des::decrypt3(const char *key, const char * sIn, size_t iInlen) { //去掉填充字符 int pad = (int)(*(ret.end() - 1)); - ret.erase(ret.end() - pad, ret.end()); + if (pad<0 || pad>(int)ret.length()) + ret.clear(); + else + ret.erase(ret.end() - pad, ret.end()); } delete []in_data; diff --git a/util/src/tc_encoder.cpp b/util/src/tc_encoder.cpp index 3a16c9205901fd152f96fec84b0b9bac1f4da90d..bb243250a51a137c0785e35e347c6fd15d7e7e4c 100644 --- a/util/src/tc_encoder.cpp +++ b/util/src/tc_encoder.cpp @@ -152,7 +152,7 @@ string TC_Encoder::gbk2utf8(const string &sIn) cd = iconv_open("UTF-8","GBK"); if (cd == (iconv_t)-1) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Encoder_Exception, "[TC_Encoder::gbk2utf8] iconv_open error"); + THROW_EXCEPTION_SYSCODE(TC_Encoder_Exception, "[TC_Encoder::gbk2utf8] iconv_open error"); // throw TC_Encoder_Exception("[TC_Encoder::gbk2utf8] iconv_open error", TC_Exception::getSystemCode()); } @@ -212,7 +212,7 @@ void TC_Encoder::gbk2utf8(const string &sIn, vector &vtStr) cd = iconv_open("UTF-8","GBK"); if (cd == (iconv_t)-1) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Encoder_Exception, "[TC_Encoder::gbk2utf8] iconv_open error"); + THROW_EXCEPTION_SYSCODE(TC_Encoder_Exception, "[TC_Encoder::gbk2utf8] iconv_open error"); // throw TC_Encoder_Exception("[TC_Encoder::gbk2utf8] iconv_open error", TC_Exception::getSystemCode()); } @@ -321,7 +321,7 @@ void TC_Encoder::utf82gbk(char *sOut, int &iMaxOutLen, const char *sIn, int iInL cd = iconv_open("GBK","UTF-8"); if (cd == (iconv_t)-1) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Encoder_Exception, "[TC_Encoder::utf82gbk] iconv_open error"); + THROW_EXCEPTION_SYSCODE(TC_Encoder_Exception, "[TC_Encoder::utf82gbk] iconv_open error"); // throw TC_Encoder_Exception("[TC_Encoder::utf82gbk] iconv_open error", TC_Exception::getSystemCode()); } @@ -335,7 +335,7 @@ void TC_Encoder::utf82gbk(char *sOut, int &iMaxOutLen, const char *sIn, int iInL { iMaxOutLen = 0; iconv_close(cd); - TARS_THROW_EXCEPTION_SYSCODE(TC_Encoder_Exception, "[TC_Encoder::utf82gbk] iconv error"); + THROW_EXCEPTION_SYSCODE(TC_Encoder_Exception, "[TC_Encoder::utf82gbk] iconv error"); // throw TC_Encoder_Exception("[TC_Encoder::utf82gbk] iconv error", TC_Exception::getSystemCode()); return; } diff --git a/util/src/tc_epoll_server.cpp b/util/src/tc_epoll_server.cpp index 2588598b7f9675297972bb3ff5975d0a1f9281e5..cb82b7534653cc1b8c6e1e20a52ec64c390afc15 100644 --- a/util/src/tc_epoll_server.cpp +++ b/util/src/tc_epoll_server.cpp @@ -3,14 +3,14 @@ * * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. * - * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * https://opensource.org/licenses/BSD-3-Clause * - * Unless required by applicable law or agreed to in writing, software distributed - * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ @@ -24,7 +24,7 @@ #include #include -#define FILE_FUNC_LINE "[" << __FILE__ << "::" << __FUNCTION__ << "::" << __LINE__ << "]" +#define FILE_FUNC_LINE "[" << __FILE__ << "::" << __FUNCTION__ << "::" << __LINE__ << "]" #define LOG_CONSOLE cout << this_thread::get_id() <<"|"<< TC_Common::now2str()<< FILE_FUNC_LINE << "|" #if TARGET_PLATFORM_WINDOWS @@ -52,7 +52,7 @@ static const int BUFFER_SIZE = 8 * 1024; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // handle的实现 -TC_EpollServer::Handle::Handle() +TC_EpollServer::Handle::Handle() : _pEpollServer(NULL) , _iWaitTime(100) { @@ -305,8 +305,6 @@ TC_EpollServer::BindAdapter::BindAdapter(TC_EpollServer *pEpollServer) TC_EpollServer::BindAdapter::~BindAdapter() { - //adapter析够的时候, 服务要退出 - // _pEpollServer->terminate(); } void TC_EpollServer::BindAdapter::setProtocolName(const string& name) @@ -426,7 +424,7 @@ void TC_EpollServer::BindAdapter::notifyHandle(uint32_t handleIndex) void TC_EpollServer::BindAdapter::insertRecvQueue(const shared_ptr &recv) { - _iBufferSize++; + _iRecvBufferSize++; size_t idx = 0; @@ -451,14 +449,19 @@ bool TC_EpollServer::BindAdapter::waitForRecvQueue(uint32_t handleIndex, shared_ return bRet; } - --_iBufferSize; + --_iRecvBufferSize; return bRet; } size_t TC_EpollServer::BindAdapter::getRecvBufferSize() const { - return _iBufferSize; + return _iRecvBufferSize; +} + +size_t TC_EpollServer::BindAdapter::getSendBufferSize() const +{ + return _iSendBufferSize; } TC_NetWorkBuffer::PACKET_TYPE TC_EpollServer::BindAdapter::echo_protocol(TC_NetWorkBuffer &r, vector &o) @@ -504,14 +507,14 @@ void TC_EpollServer::BindAdapter::setQueueCapacity(int n) int TC_EpollServer::BindAdapter::isOverloadorDiscard() { - int iRecvBufferSize = _iBufferSize; + int iRecvBufferSize = _iRecvBufferSize; if(iRecvBufferSize > (int)(_iQueueCapacity / 5.*4) && (iRecvBufferSize < _iQueueCapacity) && (_iQueueCapacity > 0)) //overload { //超过队列4/5开始认为过载 return -1; } - else if(iRecvBufferSize > (int)(_iQueueCapacity) && _iQueueCapacity > 0)//队列满需要丢弃接受的数据包 + else if(iRecvBufferSize > (int)(_iQueueCapacity) && _iQueueCapacity > 0 ) //队列满需要丢弃接受的数据包 { return -2; } @@ -609,7 +612,7 @@ const vector &TC_EpollServer::BindAdapter::getDeny() const bool TC_EpollServer::BindAdapter::isLimitMaxConnection() const { - return (_iCurConns + 1 > (size_t)_iMaxConns) || (_iCurConns + 1 > (int)((uint32_t)1 << 22) - 1); + return (_iCurConns + 1 > _iMaxConns) || (_iCurConns + 1 > (int)((uint32_t)1 << 22) - 1); } void TC_EpollServer::BindAdapter::decreaseNowConnection() @@ -683,7 +686,7 @@ TC_EpollServer::Connection::Connection(TC_EpollServer::BindAdapter *pBindAdapter , _bEmptyConn(true) , _pRecvBuffer(NULL) , _nRecvBufferSize(DEFAULT_RECV_BUFFERSIZE) - +, _authInit(false) { assert(fd != -1); @@ -720,7 +723,7 @@ TC_EpollServer::Connection::~Connection() delete _pRecvBuffer; _pRecvBuffer = NULL; } - + if (isTcp()) { assert(!_sock.isValid()); @@ -748,6 +751,8 @@ void TC_EpollServer::Connection::close() if (isTcp() && _sock.isValid()) { + _pBindAdapter->decreaseSendBufferSize(_sendBuffer.size()); + _sock.close(); } } @@ -823,7 +828,7 @@ int TC_EpollServer::Connection::parseProtocol(TC_NetWorkBuffer &rbuf) recv->buffer().swap(ro); - if (_pBindAdapter->_authWrapper && _pBindAdapter->_authWrapper(this, recv)) + if (_pBindAdapter->getEndpoint().isTcp() && _pBindAdapter->_authWrapper && _pBindAdapter->_authWrapper(this, recv)) continue; //收到完整的包才算 @@ -1003,18 +1008,32 @@ int TC_EpollServer::Connection::recv() int TC_EpollServer::Connection::sendBuffer() { + if(!isTcp()) + { + return 0; + } + + size_t nowSendBufferSize = 0; + size_t nowLeftBufferSize = _sendBuffer.getBufferLength(); + while(!_sendBuffer.empty()) { pair data = _sendBuffer.getBufferPointer(); - assert(data.first != NULL); - - int iBytesSent = _sock.send((const void *)data.first, data.second); + int iBytesSent = _sock.send((const void *) data.first, data.second); + // } + // else + // { + // iBytesSent = _sock.sendto((const void *) data.first, data.second, _ip, _port, 0); + // } if (iBytesSent < 0) { if (TC_Socket::isPending()) { +#if TARGET_PLATFORM_WINDOWS + _pBindAdapter->getNetThreadOfFd(_sock.getfd())->getEpoller()->mod(_sock.getfd(), getId(), EPOLLIN|EPOLLOUT); +#endif break; } else @@ -1026,7 +1045,24 @@ int TC_EpollServer::Connection::sendBuffer() if(iBytesSent > 0) { - _sendBuffer.moveHeader(iBytesSent); + nowSendBufferSize += iBytesSent; + + if(isTcp()) + { + _sendBuffer.moveHeader(iBytesSent); + + if (iBytesSent == (int)data.second) + { + _pBindAdapter->decreaseSendBufferSize(); + } + } + else + { + _sendBuffer.moveHeader(data.second); + + _pBindAdapter->decreaseSendBufferSize(); + + } } //发送的数据小于需要发送的,break, 内核会再通知你的 @@ -1043,52 +1079,186 @@ int TC_EpollServer::Connection::sendBuffer() return -2; } - return 0; - -} +// 当出现队列积压的前提下, 且积压超过一定大小 +// 每5秒检查一下积压情况, 连续12次(一分钟), 都是积压 +// 且每个检查点, 积压长度都增加或者连续3次发送buffer字节小于1k, 就关闭连接, 主要避免极端情况 -int TC_EpollServer::Connection::sendTcp(const shared_ptr &sc) -{ - if(!sc->buffer()->empty()) + size_t iBackPacketBuffLimit = _pBindAdapter->getBackPacketBuffLimit(); + if(_sendBuffer.getBufferLength() > iBackPacketBuffLimit) { -#if TARS_SSL - if (getBindAdapter()->getEndpoint().isSSL()) + if(_sendBufferSize == 0) + { + //开始积压 + _lastCheckTime = TNOW; + } + _sendBufferSize += nowSendBufferSize; + + if (TNOW - _lastCheckTime >= 5) { - assert(_openssl->isHandshaked()); + //如果持续有积压, 则每5秒检查一次 + _lastCheckTime = TNOW; - int ret = _openssl->write(sc->buffer()->buffer(), sc->buffer()->length(), _sendBuffer); - if (ret != 0) { - _pBindAdapter->getEpollServer()->error("[TC_EpollServer::Connection] sendTcp [" + _ip + ":" + TC_Common::tostr(_port) + "] error:" + _openssl->getErrMsg()); + _checkSend.push_back(make_pair(_sendBufferSize, nowLeftBufferSize)); + + _sendBufferSize = 0; + + size_t iBackPacketBuffMin = _pBindAdapter->getBackPacketBuffMin(); + + //连续3个5秒, 发送速度都极慢, 每5秒发送 < iBackPacketBuffMin, 认为连接有问题, 关闭之 + int left = 3; + if ((int)_checkSend.size() >= left) + { + bool slow = true; + for (int i = (int)_checkSend.size() - 1; i >= (int)(_checkSend.size() - left); i--) + { + //发送速度 + if (_checkSend[i].first > iBackPacketBuffMin) + { + slow = false; + continue; + } + } - return -1; // should not happen + if (slow) + { + ostringstream os; + os << "send [" << _ip << ":" << _port << "] buffer queue send to slow, send size:"; + + for (int i = (int)_checkSend.size() - 1; i >= (int)(_checkSend.size() - left); i--) + { + os << ", " << _checkSend[i].first; + } + + _pBindAdapter->getEpollServer()->error(os.str()); + _sendBuffer.clearBuffers(); + return -5; + } + } + + //连续12个5秒, 都有积压现象, 检查 + if (_checkSend.size() >= 12) + { + bool accumulate = true; + for (size_t i = _checkSend.size() - 1; i >= 1; i--) { + //发送buffer 持续增加 + if (_checkSend[i].second < _checkSend[i - 1].second) { + accumulate = false; + break; + } + } + + //持续积压 + if (accumulate) + { + ostringstream os; + os << "send [" << _ip << ":" << _port << "] buffer queue continues to accumulate data, queue size:"; + + for (size_t i = 0; i < _checkSend.size(); i++) + { + os << ", " << _checkSend[i].second; + } + + _pBindAdapter->getEpollServer()->error(os.str()); + _sendBuffer.clearBuffers(); + return -4; + } + + _checkSend.erase(_checkSend.begin()); } - } - else -#endif - { - _sendBuffer.addBuffer(sc->buffer()); } } + else + { + //无积压 + _sendBufferSize = 0; + _lastCheckTime = TNOW; + _checkSend.clear(); + } + + return 0; - return sendBuffer(); } +// +//int TC_EpollServer::Connection::sendTcp(const shared_ptr &sc) +//{ +//#if TARS_SSL +// if (getBindAdapter()->getEndpoint().isSSL()) +// { +// assert(_openssl->isHandshaked()); +// +// int ret = _openssl->write(sc->buffer()->buffer(), sc->buffer()->length(), _sendBuffer); +// if (ret != 0) { +// _pBindAdapter->getEpollServer()->error("[TC_EpollServer::Connection] sendTcp [" + _ip + ":" + TC_Common::tostr(_port) + "] error:" + _openssl->getErrMsg()); +// +// return -1; // should not happen +// } +// } +// else +//#endif +// { +// _sendBuffer.addBuffer(sc->buffer()); +// } +// +// return sendBuffer(); +//} +// +//int TC_EpollServer::Connection::sendUdp(const shared_ptr &sc) +//{ +// _sendBuffer.addBuffer(sc->buffer()); +// +// return sendBuffer(); +//// +//// //udp的直接发送即可 +//// int iRet = _sock.sendto((const void *) sc->buffer()->buffer(), sc->buffer()->length(), sc->ip(), sc->port(), 0); +//// if (iRet < 0) +//// { +//// _pBindAdapter->getEpollServer()->error("[TC_EpollServer::Connection] send [" + _ip + ":" + TC_Common::tostr(_port) + "] error"); +//// return -1; +//// } +//// +//// return 0; +//} -int TC_EpollServer::Connection::sendUdp(const shared_ptr &sc) +int TC_EpollServer::Connection::send(const shared_ptr &sc) { - //udp的直接发送即可 - int iRet = _sock.sendto((const void *) sc->buffer()->buffer(), sc->buffer()->length(), sc->ip(), sc->port(), 0); - if (iRet < 0) + assert(sc); + + _pBindAdapter->increaseSendBufferSize(); + + if(getBindAdapter()->getEndpoint().isTcp()) { - _pBindAdapter->getEpollServer()->error("[TC_EpollServer::Connection] send [" + _ip + ":" + TC_Common::tostr(_port) + "] error"); - return -1; - } + #if TARS_SSL + if (getBindAdapter()->getEndpoint().isSSL()) + { + assert(_openssl->isHandshaked()); - return 0; -} + int ret = _openssl->write(sc->buffer()->buffer(), sc->buffer()->length(), _sendBuffer); + if (ret != 0) + { + _pBindAdapter->getEpollServer()->error("[TC_EpollServer::Connection] send [" + _ip + ":" + TC_Common::tostr(_port) + "] error:" + _openssl->getErrMsg()); -int TC_EpollServer::Connection::send(const shared_ptr &sc) -{ - return isTcp() ? sendTcp(sc) : sendUdp(sc); + return -1; // should not happen + } + } + else + #endif + { + _sendBuffer.addBuffer(sc->buffer()); + } + + return sendBuffer(); + } + else + { + //注意udp, 回包时需要带上请求包的ip, port的 + int iRet = _sock.sendto((const void *) sc->buffer()->buffer(), sc->buffer()->length(), sc->ip(), sc->port(), 0); + if (iRet < 0) + { + _pBindAdapter->getEpollServer()->error("[TC_EpollServer::Connection] send udp [" + _ip + ":" + TC_Common::tostr(_port) + "] error"); + return -1; + } + } + return 0; } bool TC_EpollServer::Connection::setRecvBuffer(size_t nSize) @@ -1157,7 +1327,7 @@ void TC_EpollServer::ConnectionList::init(uint32_t size, uint32_t iIndex) uint32_t TC_EpollServer::ConnectionList::getUniqId() { - TC_LockT lock(_mutex); + TC_LockT lock(_mutex); uint32_t uid = _free.front(); @@ -1182,7 +1352,7 @@ TC_EpollServer::Connection* TC_EpollServer::ConnectionList::get(uint32_t uid) void TC_EpollServer::ConnectionList::add(Connection *cPtr, time_t iTimeOutStamp) { - TC_LockT lock(_mutex); + TC_LockT lock(_mutex); uint32_t muid = cPtr->getId(); uint32_t magi = muid & (0xFFFFFFFF << 22); @@ -1195,7 +1365,7 @@ void TC_EpollServer::ConnectionList::add(Connection *cPtr, time_t iTimeOutStamp) void TC_EpollServer::ConnectionList::refresh(uint32_t uid, time_t iTimeOutStamp) { - TC_LockT lock(_mutex); + TC_LockT lock(_mutex); uint32_t magi = uid & (0xFFFFFFFF << 22); uid = uid & (0x7FFFFFFF >> 9); @@ -1224,7 +1394,7 @@ void TC_EpollServer::ConnectionList::checkTimeout(time_t iCurTime) _lastTimeoutTime = iCurTime; - TC_LockT lock(_mutex); + TC_LockT lock(_mutex); multimap::iterator it = _tl.begin(); @@ -1295,7 +1465,7 @@ vector TC_EpollServer::ConnectionList::getConnStatus { vector v; - TC_LockT lock(_mutex); + TC_LockT lock(_mutex); for(size_t i = 1; i <= _total; i++) { @@ -1309,6 +1479,8 @@ vector TC_EpollServer::ConnectionList::getConnStatus cs.port = _vConn[i].first->getPort(); cs.timeout = _vConn[i].first->getTimeout(); cs.uid = _vConn[i].first->getId(); + cs.recvBufferSize = _vConn[i].first->getRecvBuffer().getBufferLength(); + cs.sendBufferSize = _vConn[i].first->getSendBuffer().getBufferLength(); v.push_back(cs); } @@ -1319,7 +1491,7 @@ vector TC_EpollServer::ConnectionList::getConnStatus void TC_EpollServer::ConnectionList::del(uint32_t uid) { - TC_LockT lock(_mutex); + TC_LockT lock(_mutex); uint32_t magi = uid & (0xFFFFFFFF << 22); uid = uid & (0x7FFFFFFF >> 9); @@ -1346,7 +1518,7 @@ void TC_EpollServer::ConnectionList::_del(uint32_t uid) size_t TC_EpollServer::ConnectionList::size() { - TC_LockT lock(_mutex); + TC_LockT lock(_mutex); return _total - _free_size; } @@ -1601,6 +1773,7 @@ void TC_EpollServer::NetThread::processPipe() if (!cPtr) { + _sbuffer.pop_front(); continue; } switch (sc->cmd()) @@ -1711,7 +1884,7 @@ void TC_EpollServer::NetThread::run() if (iEvNum == 0) { //在这里加上心跳逻辑,获取所有的bindAdpator,然后发心跳 - if (_epollServer->isMergeHandleNetThread()) + if (_epollServer->isMergeHandleNetThread()) { vector adapters = _epollServer->getBindAdapters(); for (auto adapter : adapters) @@ -1750,18 +1923,18 @@ void TC_EpollServer::NetThread::run() } } -size_t TC_EpollServer::NetThread::getSendRspSize() -{ - return _sbuffer.size(); -} +//size_t TC_EpollServer::NetThread::getSendRspSize() +//{ +// return _sbuffer.size(); +//} ////////////////////////////////////////////////////////////// TC_EpollServer::TC_EpollServer(unsigned int iNetThreadNum) : _netThreadNum(iNetThreadNum) , _bTerminate(false) , _handleStarted(false) -, _pLocalLogger(NULL) +, _pLocalLogger(NULL) { -#if TARGET_PLATFORM_WINDOWS +#if TARGET_PLATFORM_WINDOWS WSADATA wsadata; WSAStartup(MAKEWORD(2, 2), &wsadata); #endif @@ -1812,9 +1985,9 @@ TC_EpollServer::~TC_EpollServer() } _listeners.clear(); -#if TARGET_PLATFORM_WINDOWS +#if TARGET_PLATFORM_WINDOWS WSACleanup(); -#endif +#endif } void TC_EpollServer::applicationCallback(TC_EpollServer *epollServer) @@ -1848,7 +2021,7 @@ bool TC_EpollServer::accept(int fd, int domain) inet_ntop(domain, (AF_INET6 == domain) ? ( void *)&stSockAddr6.sin6_addr : ( void *)&stSockAddr4.sin_addr, sAddr, sizeof(sAddr)); port = (AF_INET6 == domain) ? ntohs(stSockAddr6.sin6_port) : ntohs(stSockAddr4.sin_port); ip = sAddr; - + debug("accept [" + ip + ":" + TC_Common::tostr(port) + "] [" + TC_Common::tostr(cs.getfd()) + "] incomming"); if (!_listeners[fd]->isIpAllow(ip)) @@ -1972,7 +2145,7 @@ void TC_EpollServer::waitForShutdown() } } } - + for (size_t i = 0; i < _netThreads.size(); ++i) { if (_netThreads[i]->isAlive()) @@ -1982,7 +2155,7 @@ void TC_EpollServer::waitForShutdown() _netThreads[i]->getThreadControl().join(); } } - + } void TC_EpollServer::terminate() diff --git a/util/src/tc_epoller.cpp b/util/src/tc_epoller.cpp index cc05f4be8bc74982aaa39b742224f1ac296642fc..ec74b09d77b1757d9d7f59717362fde166597f8e 100644 --- a/util/src/tc_epoller.cpp +++ b/util/src/tc_epoller.cpp @@ -117,7 +117,15 @@ void TC_Epoller::ctrl(SOCKET_TYPE fd, uint64_t data, uint32_t events, int op) EV_SET64(&ev[n++], fd, EVFILT_WRITE, op | EV_CLEAR, 0, 0, data, 0, 0); } - kevent64(_iEpollfd, ev, n, nullptr, 0, 0, nullptr); + int ret = kevent64(_iEpollfd, ev, n, nullptr, 0, 0, nullptr); + + if(ret == -1) + { + //一般都是析构的时候出现,有需要close就行 +// cerr << "[TC_Epoller::ctrl] error, fd:" << fd << ", errno:" << errno << "|"<< strerror(errno) << endl; + ::close(_iEpollfd); + _iEpollfd = 0; + } } #else @@ -186,7 +194,7 @@ void TC_Epoller::del(SOCKET_TYPE fd, uint64_t data, int32_t event) #if TARGET_PLATFORM_IOS ctrl(fd, data, event, EV_DELETE); #else - ctrl(fd, event, event, EPOLL_CTL_DEL); + ctrl(fd, data, event, EPOLL_CTL_DEL); #endif } diff --git a/util/src/tc_ex.cpp b/util/src/tc_ex.cpp index 78f63ba004ce5ffe1a803fa129747a8a00e48b3a..7c3b2ac95ff0321b40928e9f9816b4d12e2e58fc 100644 --- a/util/src/tc_ex.cpp +++ b/util/src/tc_ex.cpp @@ -95,12 +95,14 @@ string TC_Exception::parseError(int err) FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + NULL, err, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (LPTSTR) & lpMsgBuf, 0, NULL); // errMsg = Unicode2ANSI((LPCWSTR)lpMsgBuf); - - errMsg = lpMsgBuf; + if(lpMsgBuf != NULL) + { + errMsg = lpMsgBuf; + } LocalFree(lpMsgBuf); #endif diff --git a/util/src/tc_file.cpp b/util/src/tc_file.cpp index 6381f99dbfdc2fcbb64a0be3a5e02b66d304fa5f..5de9b3d0ce54a3b8efe7c233751153b4fedd18f7 100644 --- a/util/src/tc_file.cpp +++ b/util/src/tc_file.cpp @@ -176,7 +176,7 @@ string TC_File::getExePath() if ( count < 0 ) { - TARS_THROW_EXCEPTION_SYSCODE(TC_File_Exception, "[TC_File::getExePath] could not get exe path error"); + THROW_EXCEPTION_SYSCODE(TC_File_Exception, "[TC_File::getExePath] could not get exe path error"); // throw TC_File_Exception("[TC_File::getExePath] could not get exe path error", TC_Exception::getSystemCode()); } @@ -292,26 +292,28 @@ string TC_File::simplifyDirectory(const string& path) result = TC_Common::replace(result, "\\", "/"); #endif + string sep(FILE_SEP); + string::size_type pos; pos = 0; - while((pos = result.find(string(FILE_SEP) + FILE_SEP, pos)) != string::npos) + while((pos = result.find(sep + FILE_SEP, pos)) != string::npos) { result.erase(pos, 1); } pos = 0; - while((pos = result.find(string(FILE_SEP) + "." + FILE_SEP, pos)) != string::npos) + while((pos = result.find(sep+ "." + FILE_SEP, pos)) != string::npos) { result.erase(pos, 2); } - while(result.substr(0, 4) == string(FILE_SEP) + ".." + FILE_SEP) + while(result.substr(0, 4) == sep + ".." + FILE_SEP) { result.erase(0, 3); } - if(result.find(string(FILE_SEP) + ".." + FILE_SEP) != string::npos) + if(result.find(sep + ".." + FILE_SEP) != string::npos) { bool ab = TC_File::isAbsolute(result); @@ -350,12 +352,12 @@ string TC_File::simplifyDirectory(const string& path) #endif } - if(result == string(FILE_SEP) + ".") + if(result == sep + ".") { return result.substr(0, result.size() - 1); } - if(result.size() >= 2 && result.substr(result.size() - 2, 2) == string(FILE_SEP) + ".") + if(result.size() >= 2 && result.substr(result.size() - 2, 2) == sep + ".") { result.erase(result.size() - 2, 2); } @@ -370,7 +372,7 @@ string TC_File::simplifyDirectory(const string& path) result.erase(result.size() - 1); } - if(result == string(FILE_SEP) + "..") + if(result == sep + "..") { result = FILE_SEP; } @@ -380,20 +382,52 @@ string TC_File::simplifyDirectory(const string& path) string TC_File::load2str(const string &sFullFileName) { - ifstream ifs(sFullFileName.c_str()); + FILE *fd = TC_Port::fopen(sFullFileName.data(), "r"); + if (fd == NULL) + return ""; + + string s; + int nread = -1; + do { + char buf[8096] = {'\0'}; + nread = fread(buf, 1, sizeof(buf), fd); + if (nread > 0) + { + s.append(buf, nread); + } + } while (nread > 0); + fclose(fd); + return s; - return string(istreambuf_iterator(ifs), istreambuf_iterator()); + // ifstream ifs(sFullFileName.c_str()); + + // return string(istreambuf_iterator(ifs), istreambuf_iterator()); } bool TC_File::load2str(const string &sFullFileName, vector &data) { - ifstream ifs(sFullFileName.c_str()); - if(ifs.is_open()) - { - data.assign(istreambuf_iterator(ifs), istreambuf_iterator()); - return true; - } - return false; + FILE *fd = TC_Port::fopen(sFullFileName.data(), "rb"); + if (fd == NULL) + return false; + + int nread = -1; + do { + char buf[8096] = {'\0'}; + nread = fread(buf, 1, sizeof(buf), fd); + if (nread > 0) + { + data.insert(data.end(), buf, buf+nread); + } + } while (nread > 0); + fclose(fd); + return true; + // ifstream ifs(sFullFileName.c_str()); + // if(ifs.is_open()) + // { + // data.assign(istreambuf_iterator(ifs), istreambuf_iterator()); + // return true; + // } + // return false; } void TC_File::save2file(const string &sFullFileName, const string &sFileData) @@ -426,61 +460,97 @@ string TC_File::extractFileName(const string &sFullFileName) return ""; } - string::size_type pos = sFullFileName.rfind(FILE_SEP); - if(pos == string::npos) + string::size_type found = sFullFileName.find_last_of("/\\"); + + // string::size_type pos = sFullFileName.rfind(FILE_SEP); + if(found == string::npos) { return sFullFileName; } - return sFullFileName.substr(pos + 1); + return sFullFileName.substr(found + 1); } string TC_File::extractFilePath(const string &sFullFileName) { -#if TARGET_PLATFORM_WINDOWS - string sFullFileNameTmp = TC_Common::replace(sFullFileName, "/", "\\"); -#else - string sFullFileNameTmp = TC_Common::replace(sFullFileName, "\\", "/"); -#endif +// #if TARGET_PLATFORM_WINDOWS +// string sFullFileNameTmp = TC_Common::replace(sFullFileName, "/", "\\"); +// #else +// string sFullFileNameTmp = TC_Common::replace(sFullFileName, "\\", "/"); +// #endif - if (sFullFileNameTmp.length() <= 0) + if (sFullFileName.length() <= 0) { return string(".") + FILE_SEP; } - string::size_type pos = 0; - - for (pos = sFullFileNameTmp.length(); pos != 0; --pos) + string::size_type found = sFullFileName.find_last_of("/\\"); + if(found == string::npos) { - if (sFullFileNameTmp[pos - 1] == FILE_SEP[0]) - { - return sFullFileNameTmp.substr(0, pos); - } + return string(".") + FILE_SEP; } - return string(".") + FILE_SEP; + return sFullFileName.substr(0, found+1); + + // string::size_type pos = 0; + + // for (pos = sFullFileNameTmp.length(); pos != 0; --pos) + // { + // if (sFullFileNameTmp[pos - 1] == FILE_SEP[0]) + // { + // return sFullFileNameTmp.substr(0, pos); + // } + // } + + // return string(".") + FILE_SEP; } string TC_File::extractFileExt(const string &sFullFileName) { - string::size_type pos; - if ((pos = sFullFileName.rfind('.')) == string::npos) + string::size_type found = sFullFileName.find_last_of("/\\"); + if(found == string::npos) { - return string(""); + if ((found = sFullFileName.rfind('.')) == string::npos) + { + return string(""); + } + + return sFullFileName.substr(found+1); } + else + { + for(string::size_type i = sFullFileName.size()-1; i > found; i--) + { + if(sFullFileName[i] == '.') + { + return sFullFileName.substr(i+1); + } + } - return sFullFileName.substr(pos+1); + return ""; + } } string TC_File::excludeFileExt(const string &sFullFileName) { - string::size_type pos; - if ((pos = sFullFileName.rfind('.')) == string::npos) + string::size_type found = sFullFileName.find_last_of("./\\"); + if(found != string::npos) { - return sFullFileName; + if(sFullFileName[found] == '.') + { + return sFullFileName.substr(0, found); + } } - return sFullFileName.substr(0, pos); + return sFullFileName; + + // string::size_type pos; + // if ((pos = sFullFileName.rfind('.')) == string::npos) + // { + // return sFullFileName; + // } + + // return sFullFileName.substr(0, pos); } string TC_File::replaceFileExt(const string &sFullFileName, const string &sExt) @@ -641,12 +711,12 @@ void TC_File::copyFile(const string &sExistFile, const string &sNewFile,bool bRe std::ifstream fin(sExistFile.c_str(), ios::binary); if(!fin) { - TARS_THROW_EXCEPTION_SYSCODE(TC_File_Exception, "[TC_File::copyFile] error: "+sExistFile); + THROW_EXCEPTION_SYSCODE(TC_File_Exception, "[TC_File::copyFile] error: "+sExistFile); } std::ofstream fout(sNewFile.c_str(), ios::binary); if(!fout ) { - TARS_THROW_EXCEPTION_SYSCODE(TC_File_Exception, "[TC_File::copyFile] error: "+sNewFile); + THROW_EXCEPTION_SYSCODE(TC_File_Exception, "[TC_File::copyFile] error: "+sNewFile); } fout << fin.rdbuf(); @@ -656,7 +726,7 @@ void TC_File::copyFile(const string &sExistFile, const string &sNewFile,bool bRe TC_Port::stat_t f_stat; if (TC_Port::lstat(sExistFile.c_str(), &f_stat) == -1) { - TARS_THROW_EXCEPTION_SYSCODE(TC_File_Exception, "[TC_File::copyFile] error: "+sExistFile); + THROW_EXCEPTION_SYSCODE(TC_File_Exception, "[TC_File::copyFile] error: "+sExistFile); } TC_Port::chmod(sNewFile.c_str(),f_stat.st_mode); diff --git a/util/src/tc_http.cpp b/util/src/tc_http.cpp index c59a61e0715aad74ab9613b9ab5d723bfa3cb183..49f845b803cf83078a6e12600425ffaa13ae9440 100755 --- a/util/src/tc_http.cpp +++ b/util/src/tc_http.cpp @@ -1,2299 +1,2229 @@ -/** - * Tencent is pleased to support the open source community by making Tars available. - * - * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * Unless required by applicable law or agreed to in writing, software distributed - * under the License is distributed on an "AS IS" BASIS, WITHOUT 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 "util/tc_http.h" -#include "util/tc_port.h" -#include "util/tc_common.h" -#include "util/tc_clientsocket.h" - -namespace tars -{ - -bool TC_Http::CmpCase::operator()(const string &s1, const string &s2) const -{ - //return TC_Common::upper(s1) < TC_Common::upper(s2); - if (TC_Port::strcasecmp(s1.c_str(), s2.c_str()) < 0) - { - return true; - } - else - { - return false; - } -} - -bool TC_URL::isValid() const -{ - return !_sURL.empty(); -} - -string TC_URL::getURL() const -{ - return _sURL; -} - -string TC_URL::type2String() const -{ - switch (_iURLType) - { - case HTTP: - return "http"; - case HTTPS: - return "https"; - case FTP: - return "ftp"; - } - - return "http"; -} - -string TC_URL::getDefaultPort() const -{ - switch (_iURLType) - { - case HTTP: - return "80"; - case HTTPS: - return "443"; - case FTP: - return "21"; - } - - return "80"; -} - -bool TC_URL::isDefaultPort() const -{ - return _sPort == getDefaultPort(); -} - -string TC_URL::toURL() -{ - _sURL.clear(); - - _sURL = _sScheme; - _sURL += "://"; - - if (!_sUser.empty()) - _sURL += _sUser; - - if (!_sUser.empty() && !_sPass.empty()) - { - _sURL += ":"; - _sURL += _sPass; - } - - if (!_sUser.empty()) - _sURL += "@"; - - _sURL += _sDomain; - - if (!isDefaultPort()) - { - _sURL += ":"; - _sURL += _sPort; - } - - _sURL += getRequest(); - - return _sURL; -} - -string TC_URL::getRequest() const -{ - string sURL; - - if (!_sPath.empty()) - sURL += _sPath; - - if (!_sQuery.empty()) - sURL += "?" + _sQuery; - - if (!_sRef.empty()) - sURL += "#" + _sRef; - - return sURL; -} - -bool TC_URL::parseURL(const string &sURL) -{ - string originRequest = TC_Common::trim(sURL, " "); - - if (originRequest.empty()) - { - return false; - } - - clear(); - - int iPos = 0; - - if (TC_Port::strncasecmp(originRequest.c_str(), "http://" , 7) == 0) - { - //http开头 - _iURLType = HTTP; - iPos = 7; - _sScheme = "http"; - } - else if (TC_Port::strncasecmp(originRequest.c_str(), "https://" , 8) == 0) - { - //https开头 - _iURLType = HTTPS; - iPos = 8; - _sScheme = "https"; - } - else if (TC_Port::strncasecmp(originRequest.c_str(), "ftp://", 6) == 0) - { - //ftps开头 - _iURLType = FTP; - iPos = 6; - _sScheme = "ftp"; - } - else - { - //默认用http - _iURLType = HTTP; - iPos = 0; - _sScheme = "http"; - } - - string::size_type index = originRequest.find("/", iPos); - string::size_type nQuestionIndex = originRequest.find("?", iPos); - string::size_type nNumbersignIndex = originRequest.find("#", iPos); - - string sUrlAuthority; - string sUrlPath; - - if (nQuestionIndex < index) - { - sUrlAuthority = originRequest.substr(iPos, nQuestionIndex - iPos); - -// string sTemp = originRequest.substr(nQuestionIndex); - - sUrlPath += '/'; - sUrlPath += originRequest.substr(nQuestionIndex); - } - else if (nNumbersignIndex < index) - { - sUrlAuthority = originRequest.substr(iPos, nNumbersignIndex - iPos); - -// string sTemp = originRequest.substr(nNumbersignIndex); - - sUrlPath += '/'; - sUrlPath += originRequest.substr(nNumbersignIndex); - } - else - { - if (index == string::npos) - { - sUrlAuthority = originRequest.substr(iPos, index); - sUrlPath = ""; - } - else - { - sUrlAuthority = originRequest.substr(iPos, index - iPos); - sUrlPath = originRequest.substr(index); - } - } - - //////解析Authority - index = sUrlAuthority.find("@"); - if (index != string::npos) - { - _sUser = sUrlAuthority.substr(0, index); - _sDomain = sUrlAuthority.substr(index + 1); - } - else - { - _sDomain = sUrlAuthority; - } - - //////解析User:Pass - index = _sUser.find(":"); - if (index != string::npos) - { - _sPass = _sUser.substr(index + 1); - _sUser = _sUser.substr(0, index); - } - - //////解析Host:Port - index = _sDomain.find(":"); - if (index != string::npos) - { - _sPort = _sDomain.substr(index + 1); - - _sDomain = _sDomain.substr(0, index); - } - else - { - _sPort = getDefaultPort(); - } - - //////解析Path Query Ref - index = sUrlPath.find("?"); - if (index != string::npos) - { - _sPath = sUrlPath.substr(0, index); - _sQuery = sUrlPath.substr(index + 1); - - index = _sQuery.rfind("#"); - if (index != string::npos) - { - _sRef = _sQuery.substr(index + 1); - _sQuery = _sQuery.substr(0, index); - } - } - else - { - _sPath = sUrlPath; - _sQuery = ""; - - index = _sPath.rfind("#"); - if (index != string::npos) - { - _sRef = _sPath.substr(index + 1); - _sPath = _sPath.substr(0, index); - } - } - - if (_sPath.empty()) - { - _sPath = "/"; - } - - toURL(); - - //域名或者IP必须包含一个点 - if (_sDomain.find(".") == string::npos) - { - return false; - } - - return true; -} - -void TC_URL::specialize() -{ - //规整化路径 - /*string sUrlPath = simplePath(getPath()); - - _fragment["path"] = sUrlPath;*/ - _sPath = simplePath(getPath()); - - _sURL = toURL(); -} - -void TC_URL::clear() -{ - _sScheme = ""; - _sUser = ""; - _sPass = ""; - _sDomain = ""; - _sPort = ""; - _sPath = ""; - _sQuery = ""; - _sRef = ""; - - _sURL.clear(); -} - -string TC_URL::getScheme() const -{ - return _sScheme; -} - -string TC_URL::getUserName() const -{ - return _sUser; -} - -string TC_URL::getPassword() const -{ - return _sPass; -} - -string TC_URL::getDomain() const -{ - return _sDomain; -} - -string TC_URL::getPort() const -{ - return _sPort; -} - -string TC_URL::getPath() const -{ - return _sPath; -} - -string TC_URL::getQuery() const -{ - return _sQuery; -} - -string TC_URL::getRef() const -{ - return _sRef; -} - -//string TC_URL::getFragment(const string& frag) const -//{ -// map::const_iterator it = _fragment.find(frag); -// if(it == _fragment.end()) -// { -// return ""; -// } -// -// return it->second; -//} - -string TC_URL::getRelativePath() const -{ - string sURL = getPath(); - - string::size_type pos; - - - pos = sURL.rfind("/"); - - if (pos == string::npos) - { - return "/"; - } - else - { - return sURL.substr(0, pos + 1); - } -} - -string TC_URL::getRootPath() const -{ - string sURL = _sScheme; - sURL += "://"; - - if (!_sUser.empty()) - sURL += _sUser; - - if (!_sUser.empty() && !_sPass.empty()) - { - sURL += ":"; - sURL += _sPass; - } - - if (!_sUser.empty()) - sURL += "@"; - - sURL += _sDomain; - - if (!isDefaultPort()) - { - sURL += ":"; - sURL += _sPort; - } - - sURL += "/"; - - return sURL; -} - -TC_URL TC_URL::buildWithRelativePath(const string &sRelativePath) const -{ - string sURL; - - if (!sRelativePath.empty() && sRelativePath[0] == '/') - { - //如果链接是用"/"开头的相对地址,那么应该用Host+相对地址 - sURL = sRelativePath.substr(1); - } - else if (sRelativePath[0] == '#') - { - //# - sURL = getPath().substr(1); - - if (!getQuery().empty()) - sURL += "?" + getQuery(); - - sURL += sRelativePath; - - } - else - { - //相对地址 - sURL = getRelativePath().substr(1) + sRelativePath; - } - - sURL = getRootPath() + simplePath("/" + sURL).substr(1); - - TC_URL url; - - url.parseURL(sURL); - - return url; -} - -string TC_URL::simplePath(const string &sPath) const -{ - //所有./都去掉 - size_t pos = 0; - string sNewPath = sPath; - - while (true) - { - size_t dotPos = sNewPath.find("./", pos); - - if (dotPos != string::npos) - { - if ((dotPos == 0) || (sNewPath.at(dotPos - 1) == '/')) - { - sNewPath.erase(dotPos, 2); - } - else - { - pos = dotPos + 2; - } - } - else - { - break; - } - } - - //如果路径是以.结尾的, 则.去掉 - if (((sNewPath.length() >= 2) && (sNewPath.substr(sNewPath.length() - 2) == "/.")) || (sNewPath == ".")) - { - sNewPath.erase(sNewPath.length() - 1); - } - - //处理/../的形式 - pos = 0; - size_t startPos = 0; - - while (1) - { - size_t slashDot = sNewPath.find("/../", pos); - - if (slashDot != string::npos) - { - if (0 == slashDot) - { - sNewPath.erase(0, 3); - continue; - } - - if ( (slashDot > 1) && (sNewPath.substr(slashDot - 2, 2) == "..") ) - { - pos = slashDot + 4; - continue; - } - - startPos = sNewPath.rfind('/', slashDot - 1); - - if (startPos == string::npos) startPos = 0; - - sNewPath.erase(startPos, slashDot + 4 - startPos - 1); - } - else - { - break; - } - } - - //处理/..结尾的情况 - if ((sNewPath.size() >= 3) && (sNewPath.substr(sNewPath.size() - 3, 3) == "/..")) - { - size_t slashDot = sNewPath.size() - 3; - if (!((slashDot > 1) && (sNewPath.substr(slashDot - 2, 2) == ".."))) - { - startPos = sNewPath.rfind ('/', slashDot - 1); - if (startPos == string::npos) startPos = 0; - sNewPath.erase (startPos + 1); - } - } - - return sNewPath; -} - -//////////////////////////////////////////////////////////////////// - -void TC_Http::setHeader(const string &sHeadName, const string &sHeadValue) -{ - //Set-Cookie和Cookie可以有多个头 - const char * pStr1 = "SET-COOKIE"; - const char * pStr2 = "COOKIE";//原则上COOKIE只有一个,担心有兼容性问题,保留 - if ((TC_Port::strcasecmp(sHeadName.c_str(), pStr1) != 0) && (TC_Port::strcasecmp(sHeadName.c_str(), pStr2) != 0)) - { - _headers.erase(sHeadName); - } - - _headers.insert(multimap::value_type(sHeadName, sHeadValue)); -} - -string TC_Http::getHeader(const string& sHeader) const -{ - http_header_type::const_iterator it = _headers.find(sHeader); - if (it == _headers.end()) - { - return ""; - } - - return it->second; -} - -string TC_Http::getContentType() const -{ - return getHeader("Content-Type"); -} - -string TC_Http::getHost() const -{ - return getHeader("Host"); -} - -size_t TC_Http::getContentLength() const -{ - string s = getHeader("Content-Length"); - if (s.empty()) - { - return 0; - } - - return TC_Common::strto(s); -} - -string TC_Http::genHeader() const -{ - string sHttpHeader; - - for (http_header_type::const_iterator it = _headers.begin(); it != _headers.end(); ++it) - { - if (it->second != "") - { - sHttpHeader += it->first; - sHttpHeader += ": "; - sHttpHeader += it->second; - sHttpHeader += "\r\n"; - } - } - - return sHttpHeader; -} - -vector TC_Http::getHeaderMulti(const string &sHeadName) const -{ - vector v; - - http_header_type::const_iterator itEnd = _headers.end(); - - for ( http_header_type::const_iterator it = _headers.begin(); it != itEnd; ++it) - { - if (TC_Port::strcasecmp(it->first.c_str(), sHeadName.c_str()) == 0) - { - v.push_back(it->second); - } - } - - return v; -} - -string TC_Http::getLine(const char** ppChar) -{ - string sTmp; - - sTmp.reserve(512); - - while ((**ppChar) != '\r' && (**ppChar) != '\n' && (**ppChar) != '\0') - { - sTmp.append(1, (**ppChar)); - (*ppChar)++; - } - - if ((**ppChar) == '\r') - { - (*ppChar)++; /* pass the char '\n' */ - } - - (*ppChar)++; - - return sTmp; -} - - -string TC_Http::getLine(const char** ppChar, int iBufLen) -{ - string sTmp; - - sTmp.reserve(512); - - int iCurIndex = 0; - while ( (**ppChar) != '\r' && (**ppChar) != '\n' && (**ppChar) != '\0') - { - if ( iCurIndex < iBufLen ) - { - sTmp.append(1, (**ppChar)); - (*ppChar)++; - iCurIndex++; - } - else - { - //MTT_ERRDAY << "parseHttp WARN: iCurIndex < iBufLen 1 " << endl; - break; - } - } - - if ( (**ppChar) == '\r') - { - if ( iCurIndex < iBufLen ) - { - (*ppChar)++; /* pass the char '\n' */ - iCurIndex++; - } - else - { - //MTT_ERRDAY << "parseHttp WARN: iCurIndex < iBufLen 2 " << endl; - } - } - - if ( iCurIndex < iBufLen ) - { - (*ppChar)++; - iCurIndex++; - } - else - { - //MTT_ERRDAY << "parseHttp WARN: iCurIndex < iBufLen 3 " << endl; - } - - return sTmp; -} - - -const char* TC_Http::parseHeader(const char* szBuffer, http_header_type &sHeader) -{ - sHeader.clear(); - - const char **ppChar = &szBuffer; - - size_t length = strlen(szBuffer); - size_t srcPtr = (size_t)(*ppChar); - - while (true) - { - string sLine = getLine(ppChar); - - if (sLine.empty()) break; - - //如果是第一行, 则忽略掉 - if(TC_Port::strncasecmp(sLine.c_str(), "GET ", 4) ==0 - || TC_Port::strncasecmp(sLine.c_str(), "POST ", 5) ==0 - || TC_Port::strncasecmp(sLine.c_str(), "PUT ", 4) ==0 - || TC_Port::strncasecmp(sLine.c_str(), "PATCH ", 6) ==0 - || TC_Port::strncasecmp(sLine.c_str(), "OPTIONS ", 8) ==0 - || TC_Port::strncasecmp(sLine.c_str(), "HEAD ", 5) ==0 - || TC_Port::strncasecmp(sLine.c_str(), "DELETE ", 7) ==0 - || TC_Port::strncasecmp(sLine.c_str(), "HTTP/", 5) ==0) - { - continue; - } - - string::size_type index = sLine.find(":"); - if(index != string::npos) - { - sHeader.insert(multimap::value_type(TC_Common::trim(sLine.substr(0, index), " "), TC_Common::trim(sLine.substr(index + 1), " "))); - } - - size_t offset = (size_t)(*ppChar - srcPtr); - - if(offset >= length) - { - break; - } - } - - return *ppChar; -} - -void TC_Http::reset() -{ - _headers.clear(); - _headLength = 0; - _content.clear(); - _bIsChunked = false; -} - -void TC_Http::getHeaders(map &header) -{ - for(auto it = _headers.begin(); it != _headers.end(); ++it) - { - header.insert(map::value_type(it->first, it->second)); - } -} - -/********************* TC_HttpCookie ***********************/ - -bool TC_HttpCookie::matchDomain(const string &sCookieDomain, const string &sDomain) -{ - string sCookieDomainNew = TC_Common::lower(sCookieDomain); - - //没有点的自动加点 - if (sCookieDomainNew.find(".") != 0) - { - sCookieDomainNew = "." + sCookieDomainNew; - } - - string::size_type pos = sCookieDomainNew.find("."); - - //sCookieDomain串至少有两个点 - if (pos == string::npos || (pos == 0 && sCookieDomainNew.rfind(".") == 0)) - { - return false; - } - - string sLowerDomain = TC_Common::lower(sDomain); - - //后边是子域名 - if (sDomain.length() >= sCookieDomainNew.length() && - sLowerDomain.compare(sDomain.length() - sCookieDomainNew.length(), sCookieDomainNew.length(), sCookieDomainNew) == 0) - { - return true; - } - - //去掉.相等 - if (sLowerDomain == sCookieDomainNew.substr(1)) - { - return true; - } - - return false; -} - -size_t TC_HttpCookie::matchPath(const string &sCookiePath, const string &sPath) -{ - if (sCookiePath.empty() || sPath.empty()) return 0; - - //都在最后加/再匹配 - string sCookiePath1 = (sCookiePath.at(sCookiePath.length() - 1) == '/') ? sCookiePath : sCookiePath + "/"; - - string sPath1 = (sPath.at(sPath.length() - 1) == '/') ? sPath : sPath + "/"; - - if (sPath1.find(sCookiePath1) == 0) - { - return sCookiePath1.length(); - } - - return 0; -} - -void TC_HttpCookie::clear() -{ - _cookies.clear(); -} - -bool TC_HttpCookie::fixDomain(const string &sDomain, string &sFixDomain) -{ - if (sDomain.empty()) - { - return false; - } - - sFixDomain = sDomain; - - //自动加. - if (sDomain.at(0) != '.') - { - sFixDomain = "." + sDomain; - } - - //domain至少两段 - if (sFixDomain.find(".") == sFixDomain.rfind(".")) - return false; - - return true; -} - -void TC_HttpCookie::addCookie(const Cookie &cookie, list &cookies) -{ - string sDomain; - - Cookie cookieNew = cookie; - - if (!fixDomain(cookieNew._domain, sDomain)) - return; - - cookieNew._domain = sDomain; - - if (cookieNew._path.empty()) - return; - - list::iterator it = cookies.begin(); - - string sName; - if (cookieNew._data.size() >= 1) - { - sName = cookieNew._data.begin()->first; - } - - while (it != cookies.end()) - { - //检查Cookie是否过期 - if (isCookieExpires(*it)) - { - cookies.erase(it++); - } - else if (TC_Port::strcasecmp(it->_domain.c_str(), cookieNew._domain.c_str()) == 0 - && strcmp(it->_path.c_str(), cookieNew._path.c_str()) == 0 - && it->_isSecure == cookieNew._isSecure) - { - if (it->_expires == cookieNew._expires) - { - //domain/path/expires都匹配的情况下, 覆盖老cookie的数据 - cookieNew._data.insert(it->_data.begin(), it->_data.end()); - - cookies.erase(it++); - } - else - { - //超时间不一样,但存在同样的key,需删除 - if (it->_data.find(sName) != it->_data.end()) - { - it->_data.erase(sName); - } - ++it; - } - } - else - { - ++it; - } - } - - cookies.push_back(cookieNew); -} - -void TC_HttpCookie::addCookie(const Cookie &cookie) -{ - addCookie(cookie, _cookies); -} - -void TC_HttpCookie::addCookie(const list &cookie) -{ - list::const_iterator it = cookie.begin(); - - while (it != cookie.end()) - { - addCookie(*it); - - ++it; - } -} - -void TC_HttpCookie::addCookie(const string &sRspURL, const vector &vCookies) -{ - TC_URL cURL; - - cURL.parseURL(sRspURL); - - string sRspURLDomain = TC_Common::lower(cURL.getDomain()); - - string sRspURLPath = cURL.getPath(); - - for (size_t i = 0; i < vCookies.size(); i++) - { - //处理一行SetCookie - vector v = TC_Common::sepstr(vCookies[i], ";"); - - Cookie cookie; - - cookie._isSecure = false; - cookie._expires = 0; - - //解析Cookie数据 - for (size_t j = 0; j < v.size(); ++j) - { - string::size_type index = v[j].find("="); - - string name; - - string value; - - if (index != string::npos) - { - name = TC_Common::trim(v[j].substr(0, index), " "); - - value = TC_Common::trim(v[j].substr(index + 1)); - } - else - { - name = TC_Common::trim(v[j]); - } - if (TC_Port::strcasecmp(name.c_str(), "secure") == 0) - { - cookie._isSecure = true; - } - else if (TC_Port::strcasecmp(name.c_str(), "expires") == 0) - { - struct tm stTm; - //兼容时间格式 - //expires=Mon, 09-May-41 08:39:32 GMT - //expires=Thu, 01-Jan-1970 01:00:00 GMT - value = TC_Common::replace(value, "-", " "); - if (value.length() == 27 && value.at(11) == ' ' && value.at(14) == ' ') - { - int year = TC_Common::strto (value.substr(12, 2)); - if (year >= 69 && year <= 99) - value = value.substr(0, 12) + "19" + value.substr(12); - else - value = value.substr(0, 12) + "20" + value.substr(12); - } - - TC_Common::strgmt2tm(value, stTm); - - cookie._expires = TC_Port::timegm(&stTm); - } - else if (TC_Port::strcasecmp(name.c_str(), "path") == 0) - { - cookie._path = value; - } - else if (TC_Port::strcasecmp(name.c_str(), "domain") == 0) - { - cookie._domain = value; - } - else if (TC_Port::strcasecmp(name.c_str(), "httponly") == 0) - { - //TODO - //cookie._isHttpOnly = true; - } - else - cookie._data.insert(http_cookie_data::value_type(name, value)); - } - - ///修正和匹配domain///////////////////////////////////////// - if (cookie._domain.empty()) - cookie._domain = sRspURLDomain; - - if (!fixDomain(cookie._domain, cookie._domain)) - continue; - - //匹配域名 - if (!matchDomain(cookie._domain, sRspURLDomain)) - continue; - - //修改和匹配path///////////////////////////// - if (cookie._path.empty()) - { - string sCookiePath; - - //缺省是全路径 - string sRequest = sRspURLPath; - - string::size_type pos = sRequest.rfind("/"); - - if (pos == string::npos) - sCookiePath = "/"; - else - sCookiePath = sRequest.substr(0, pos + 1); - - cookie._path = sCookiePath; - } - - //URL在Path范围内,Cookie 有效 - if(!matchPath(cookie._path, sRspURLPath)) - continue; - - //添加Cookie - addCookie(cookie); - } -} - -bool TC_HttpCookie::isCookieExpires(const Cookie &cookie) const -{ - //过期了 - if(cookie._expires !=0 && cookie._expires < time(NULL)) - return true; - - return false; -} - -size_t TC_HttpCookie::isCookieMatch(const Cookie &cookie, const TC_URL &tURL) const -{ - //域名没有匹配 - if(!matchDomain(cookie._domain, tURL.getDomain())) - return 0; - - //路径没有匹配 - size_t len = matchPath(cookie._path, tURL.getPath()); - if(len == 0) - return 0; - - //安全的cookie,不安全的URL - if(cookie._isSecure && (tURL.getType() != TC_URL::HTTPS)) - return 0; - - return len; -} - -void TC_HttpCookie::getCookieForURL(const string &sReqURL, list &cookies) -{ - TC_URL tURL; - - tURL.parseURL(sReqURL); - - cookies.clear(); - - list::iterator it = _cookies.begin(); - - while(it != _cookies.end()) - { - //检查Cookie是否过期 - if(isCookieExpires(*it)) - { - _cookies.erase(it++); - continue; - } - - size_t len = isCookieMatch(*it, tURL); - if(len == 0) - { - ++it; - continue; - } - - cookies.push_back(*it); - - ++it; - } -} - -void TC_HttpCookie::getCookieForURL(const string &sReqURL, string &sCookie) -{ - list cookies; - - sCookie.clear(); - - getCookieForURL(sReqURL, cookies); - - list::iterator it = cookies.begin(); - while(it != cookies.end()) - { - http_cookie_data::iterator itd = it->_data.begin(); - - while(itd != it->_data.end()) - { - //被删除的cookie不输出 - if(itd->first != "" && itd->second != "" && TC_Common::lower(itd->second) != "null" - && TC_Common::lower(itd->second) != "deleted") - sCookie += itd->first + "=" + itd->second + "; "; - - ++itd; - } - - ++it; - } - - //去掉末尾的 "; " - if(sCookie.length() >= 2) - sCookie = sCookie.substr(0, sCookie.length()-2); -} - -list TC_HttpCookie::getSerializeCookie(time_t t) -{ - list cookies; - - list::iterator it = _cookies.begin(); - - while(it != _cookies.end()) - { - if(isCookieExpires(*it)) - { - _cookies.erase(it++); - continue; - } - else if(it->_expires != 0) //非当前会话的 - { - cookies.push_back(*it); - - ++it; - } - else - ++it; - } - - return cookies; -} - -const list & TC_HttpCookie::getAllCookie() -{ - deleteExpires(time(NULL)); - - return _cookies; -} - -void TC_HttpCookie::deleteExpires(time_t t, bool bErase) -{ - list::iterator it = _cookies.begin(); - - while(it != _cookies.end()) - { - if(bErase && it->_expires ==0) - { - _cookies.erase(it++); - continue; - } - else if(isCookieExpires(*it)) - { - _cookies.erase(it++); - continue; - } - else - ++it; - } -} - -/********************* TC_HttpResponse ***********************/ - -void TC_HttpResponse::parseResponseHeader(const char* szBuffer) -{ - const char **ppChar = &szBuffer; - - _headerLine = TC_Common::trim(getLine(ppChar)); - - string::size_type pos = _headerLine.find(' '); - - if(pos != string::npos) - { - _version = _headerLine.substr(0, pos); - - string left = TC_Common::trim(_headerLine.substr(pos)); - - string::size_type pos1 = left.find(' '); - - if(pos1 != string::npos) - { - _status = TC_Common::strto(left.substr(0, pos)); - - _about = TC_Common::trim(left.substr(pos1 + 1)); - } - else - { - _status = TC_Common::strto(left); - - _about = ""; - } - - parseHeader(*ppChar, _headers); - return; - } - else - { - _version = _headerLine; - _status = 0; - _about = ""; - } - -// throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response format error : " + _headerLine); -} - -void TC_HttpResponse::reset() -{ - TC_Http::reset(); - - _status = 200; - _about = "OK"; - _version = "HTTP/1.1"; - - _iTmpContentLength = 0; - _iRecvContentLength = 0; -} - -vector TC_HttpResponse::getSetCookie() const -{ - return getHeaderMulti("Set-Cookie"); -} -void TC_HttpResponse::addContent(const string &sBuffer) -{ - _content += sBuffer; - _iRecvContentLength += sBuffer.length(); -} - -bool TC_HttpResponse::incrementDecode(string &sBuffer) -{ - //解析头部 - if(_headLength == 0) - { - string::size_type pos = sBuffer.find("\r\n\r\n"); - - if(pos == string::npos) - { - return false; - } - - parseResponseHeader(sBuffer.c_str()); - - if ( (204 == _status) || (304 == _status) ) - { - return true; - } - - http_header_type::const_iterator it = _headers.find("Content-Length"); - if(it != _headers.end()) - { - _iTmpContentLength = getContentLength(); - } - else - { - //没有指明ContentLength, 接收到服务器关闭连接 - _iTmpContentLength = -1; - } - - _headLength = pos + 4; - - sBuffer = sBuffer.substr(_headLength); - - //重定向就认为成功了 - if((_status == 301 || _status == 302) && !getHeader("Location").empty()) - { - return true; - } - - //是否是chunk编码 - _bIsChunked = (getHeader("Transfer-Encoding") == "chunked"); - - //删除头部里面 - eraseHeader("Transfer-Encoding"); - } - - if(_bIsChunked) - { - while(true) - { - string::size_type pos = sBuffer.find("\r\n"); - if(pos == string::npos) - return false; - - //查找当前chunk的大小 - string sChunkSize = sBuffer.substr(0, pos); - int iChunkSize = strtol(sChunkSize.c_str(), NULL, 16); - - if(iChunkSize <= 0) break; //所有chunk都接收完毕 - - if (sBuffer.length() < pos + 2 + (size_t)iChunkSize + 2) - { - //获取一个chunk的内容 - - //删除一个chunk - //没有接收完整的chunk - return false; - } - - addContent(sBuffer.substr(pos + 2, iChunkSize)); - sBuffer = sBuffer.substr(pos + 2 + iChunkSize + 2); - // setContentLength(getContent().length()); - } - - sBuffer = ""; - - //接收到buffer长度设置好 - setContentLength(_iRecvContentLength); - - return true; - } - else - { - if(_iTmpContentLength == 0) - { - //header长度为0, 但是有body数据 - addContent(sBuffer); - sBuffer = ""; - - setContentLength(_iRecvContentLength); - //自动填写content-length - // setContentLength(getContent().length()); - - return true; - } - else if(_iTmpContentLength == (size_t)-1) - { - //304的返回码中头没有Content-Length,不会有数据体 - if (_status == 304 || _status == 302) - { - return true; - } - - //header中没长度, 但是有body数据 - addContent(sBuffer); - sBuffer = ""; - - setContentLength(_iRecvContentLength); - //自动填写content-length - // setContentLength(getContent().length()); - - return false; - } - else - { - //头部有长度, 接收到长度大于头部为止 - addContent(sBuffer); - sBuffer = ""; - - // size_t iNowLength = getContent().length(); - - //头部的长度小于接收的内容, 还需要继续增加解析后续的buffer - if (_iTmpContentLength > _iRecvContentLength) - return false; - - return true; - } - } - - return true; -} - -bool TC_HttpResponse::decode(const string &sBuffer) -{ - string::size_type pos = sBuffer.find("\r\n\r\n"); - - if(pos == string::npos) - { - return false; - } - - string tmp = sBuffer; - - incrementDecode(tmp); - - //body内容长度为0或者没有content-length 且 非chunk模式, 则认为包收全了, 直接返回 - if((_iTmpContentLength == 0 || _iTmpContentLength == (size_t)-1) && !_bIsChunked) - return true; - - return getContentLength() + getHeadLength() <= sBuffer.length(); -} - -bool TC_HttpResponse::decode(const char *sBuffer, size_t iLength) -{ - assert(sBuffer != NULL); - - const char *p = strstr(sBuffer, "\r\n\r\n"); - if( p == NULL) - { - return false; - } - - string tmp(sBuffer, iLength); - - incrementDecode(tmp); - - //body内容长度为0或者没有content-length 且 非chunk模式, 则认为包收全了, 直接返回 - if((_iTmpContentLength == 0 || _iTmpContentLength == (size_t)-1) && !_bIsChunked) - return true; - - return (getContentLength() + getHeadLength() <= iLength); -} - -string TC_HttpResponse::encode() const -{ - string sRet; - sRet += _version; - sRet += " "; - sRet += TC_Common::tostr(_status); - sRet += " "; - sRet += _about; - sRet += "\r\n"; - sRet += genHeader(); - sRet += "\r\n"; - sRet += _content; - - return sRet; -} - -void TC_HttpResponse::encode(vector &buffer) const -{ - buffer.clear(); - - string s = encode(); - - buffer.resize(s.length()); - memcpy(buffer.data(), s.c_str(), s.length()); -} - -void TC_HttpResponse::setResponse(int status, const string& about, const string& body) -{ - _status = status; - _about = about; - _content= body; - - /*ostringstream os; - - os << _version << " " << _status << " " << _about; - - _headerLine = os.str();*/ - _headerLine = ""; - _headerLine += _version; - _headerLine += " "; - _headerLine += TC_Common::tostr(_status); - _headerLine += " "; - _headerLine += _about; - - setHeader("Content-Length", TC_Common::tostr(_content.length())); -} - -void TC_HttpResponse::setResponse(int status, const string& about, const char *sBuffer, size_t iLength) -{ - _status = status; - _about = about; - - /*ostringstream os; - - os << _version << " " << _status << " " << _about; - - _headerLine = os.str();*/ - _headerLine = ""; - _headerLine += _version; - _headerLine += " "; - _headerLine += TC_Common::tostr(_status); - _headerLine += " "; - _headerLine += _about; - - if(sBuffer != NULL && iLength > 0) - { - _content.assign(sBuffer, iLength); - } - else - { - _content.clear(); - } - - - setHeader("Content-Length", TC_Common::tostr(_content.length())); -} - -void TC_HttpResponse::setResponse(const char *sBuffer, size_t iLength) -{ - setResponse(200, "OK", sBuffer, iLength); -} - -/********************* TC_HttpRequest ***********************/ - -void TC_HttpRequest::reset() -{ - TC_Http::reset(); - - _httpURL.clear(); -} - -string TC_HttpRequest::requestType2str(int iRequestType) const -{ - if(iRequestType == REQUEST_GET) - { - return "GET"; - } - else if(iRequestType == REQUEST_HEAD) - { - return "HEAD"; - } - else if(iRequestType == REQUEST_POST) - { - return "POST"; - } - else if(iRequestType == REQUEST_OPTIONS) - { - return "OPTIONS"; - } - else if(iRequestType == REQUEST_PUT) - { - return "PUT"; - } - else if(iRequestType == REQUEST_DELETE) - { - return "DELETE"; - } - else if(iRequestType == REQUEST_PATCH) - { - return "PATCH"; - } -// assert(true); - return ""; -} - -vector TC_HttpRequest::getCookie() -{ - vector v; - - http_header_type::const_iterator itEnd = _headers.end(); - - for( http_header_type::const_iterator it = _headers.begin(); it != itEnd; ++it) - { - if(it->first == "Cookie") - { - v.push_back(it->second); - } - } - - return v; -} - -void TC_HttpRequest::parseURL(const string& sUrl) -{ - _httpURL.parseURL(sUrl); - - //设置Host - if(getHeader("Host").empty()) - { - string sPort = _httpURL.isDefaultPort() ? "" : ":" + _httpURL.getPort(); - - //缺省端口可以不用放进去 - setHost(_httpURL.getDomain() + sPort); - } -} - -void TC_HttpRequest::encode(int iRequestType, ostream &os) -{ - os << requestType2str(iRequestType) << " " << _httpURL.getRequest() << " HTTP/1.1\r\n"; - os << genHeader(); - os << "\r\n"; -} - -void TC_HttpRequest::setRequest(const string& method, const string &sUrl, const std::string& body, bool bNewCreateHost) -{ - // std::string lowMethod(method); - // std::transform(method.begin(), method.end(), lowMethod.begin(), ::tolower); - - if (TC_Port::strncasecmp(method.c_str(), "GET", 3) == 0) - setGetRequest(sUrl, bNewCreateHost); - else if (TC_Port::strncasecmp(method.c_str(), "HEAD", 4) == 0) - setHeadRequest(sUrl, bNewCreateHost); - else if (TC_Port::strncasecmp(method.c_str(), "POST", 4) == 0) - setPostRequest(sUrl, body, bNewCreateHost); - else if (TC_Port::strncasecmp(method.c_str(), "PUT", 3) == 0) - setPutRequest(sUrl, body, bNewCreateHost); - else if (TC_Port::strncasecmp(method.c_str(), "DELETE", 6) == 0) - setDeleteRequest(sUrl, body, bNewCreateHost); - else if (TC_Port::strncasecmp(method.c_str(), "PATH", 5) == 0) - setPatchRequest(sUrl, body, bNewCreateHost); -} - -void TC_HttpRequest::setGetRequest(const string &sUrl, bool bNewCreateHost) -{ - if(bNewCreateHost) - { - eraseHeader("Host"); - } - - parseURL(sUrl); - - _requestType = REQUEST_GET; - - _content = ""; - - eraseHeader("Content-Length"); -} - -void TC_HttpRequest::setHeadRequest(const string &sUrl, bool bNewCreateHost) -{ - if(bNewCreateHost) - { - eraseHeader("Host"); - } - - parseURL(sUrl); - - _requestType = REQUEST_HEAD; - - _content = ""; - - eraseHeader("Content-Length"); -} - -void TC_HttpRequest::setPostRequest(const string &sUrl, const string &sPostBody, bool bNewCreateHost) -{ - if(bNewCreateHost) - { - eraseHeader("Host"); - } - - parseURL(sUrl); - - _requestType = REQUEST_POST; - - _content = sPostBody; - - setHeader("Content-Length", TC_Common::tostr(_content.length())); -} - -void TC_HttpRequest::setOptionsRequest(const string &sUrl, bool bNewCreateHost) -{ - if (bNewCreateHost) - { - eraseHeader("Host"); - } - parseURL(sUrl); - _requestType = REQUEST_OPTIONS; - _content = ""; - eraseHeader("Content-Length"); -} -void TC_HttpRequest::setPostRequest(const string &sUrl, const char *sBuffer, size_t iLength, bool bNewCreateHost) -{ - assert(sBuffer != NULL); - if (bNewCreateHost) - { - eraseHeader("Host"); - } - parseURL(sUrl); - _requestType = REQUEST_POST; - if (iLength > 0) - { - _content.assign(sBuffer, iLength); - } - else - { - _content.clear(); - } - setHeader("Content-Length", TC_Common::tostr(_content.length())); -} -void TC_HttpRequest::setPutRequest(const string &sUrl, const string &sPostBody, bool bNewCreateHost ) -{ - if(bNewCreateHost) - { - eraseHeader("Host"); - } - - parseURL(sUrl); - - _requestType = REQUEST_PUT; - - _content = sPostBody; - - setHeader("Content-Length", TC_Common::tostr(_content.length())); -} - -void TC_HttpRequest::setPatchRequest(const string &sUrl, const string &sPostBody, bool bNewCreateHost ) -{ - if(bNewCreateHost) - { - eraseHeader("Host"); - } - - parseURL(sUrl); - - _requestType = REQUEST_PATCH; - - _content = sPostBody; - - setHeader("Content-Length", TC_Common::tostr(_content.length())); -} - - -void TC_HttpRequest::setDeleteRequest(const string &sUrl, const string &sPostBody, bool bNewCreateHost ) -{ - if(bNewCreateHost) - { - eraseHeader("Host"); - } - - parseURL(sUrl); - - _requestType = REQUEST_DELETE; - - _content = sPostBody; - - setHeader("Content-Length", TC_Common::tostr(_content.length())); - -} - -string TC_HttpRequest::encode() -{ -// assert(_requestType == REQUEST_GET || _requestType == REQUEST_POST || !_originRequest.empty()); - - /*ostringstream os; - - if(_requestType == REQUEST_GET) - { - encode(REQUEST_GET, os); - } - else if(_requestType == REQUEST_POST) - { - setContentLength(_content.length()); - encode(REQUEST_POST, os); - os << _content; - } - else if(_requestType == REQUEST_OPTIONS) - { - encode(REQUEST_OPTIONS, os); - } - - return os.str();*/ - string sRet; - - if(_requestType == REQUEST_GET) - { - //encode(REQUEST_GET, os); - sRet += requestType2str(_requestType); - sRet += " "; - sRet += _httpURL.getRequest(); - sRet += " HTTP/1.1\r\n"; - sRet += genHeader(); - sRet += "\r\n"; - } - else if(_requestType == REQUEST_POST) - { - setContentLength(_content.length()); - //encode(REQUEST_POST, os); - sRet += requestType2str(_requestType); - sRet += " "; - sRet += _httpURL.getRequest(); - sRet += " HTTP/1.1\r\n"; - sRet += genHeader(); - sRet += "\r\n"; - sRet += _content; - } - else if(_requestType == REQUEST_OPTIONS) - { - //encode(REQUEST_OPTIONS, os); - sRet += requestType2str(_requestType); - sRet += " "; - sRet += _httpURL.getRequest(); - sRet += " HTTP/1.1\r\n"; - sRet += genHeader(); - sRet += "\r\n"; - } - else if(_requestType == REQUEST_HEAD) - { - sRet += requestType2str(_requestType); - sRet += " "; - sRet += _httpURL.getRequest(); - sRet += " HTTP/1.1\r\n"; - sRet += genHeader(); - sRet += "\r\n"; - } - else if(_requestType == REQUEST_PUT || _requestType == REQUEST_PATCH) - { - setContentLength(_content.length()); - sRet += requestType2str(_requestType); - sRet += " "; - sRet += _httpURL.getRequest(); - sRet += " HTTP/1.1\r\n"; - sRet += genHeader(); - sRet += "\r\n"; - sRet += _content; - } - else if(_requestType == REQUEST_DELETE) - { - setContentLength(_content.length()); - //encode(REQUEST_GET, os); - sRet += requestType2str(_requestType); - sRet += " "; - sRet += _httpURL.getRequest(); - sRet += " HTTP/1.1\r\n"; - sRet += genHeader(); - sRet += "\r\n"; - sRet += _content; - } - - return sRet; -} - -void TC_HttpRequest::encode(vector &buffer) -{ - buffer.clear(); - - string s = encode(); - buffer.resize(s.length()); - memcpy(buffer.data(), s.c_str(), s.length()); -} - -bool TC_HttpRequest::decode(const string &sBuffer) -{ - return decode(sBuffer.c_str(), sBuffer.length()); -} - -bool TC_HttpRequest::decode(const char *sBuffer, size_t iLength) -{ - assert(sBuffer != NULL); - - if(TC_Port::strncasecmp(sBuffer, "GET " ,4) !=0 && - TC_Port::strncasecmp(sBuffer, "POST " ,5) !=0 && - TC_Port::strncasecmp(sBuffer, "PUT " ,4) !=0 && - TC_Port::strncasecmp(sBuffer, "PATCH " ,6) !=0 && - TC_Port::strncasecmp(sBuffer, "OPTIONS " ,8) !=0 && - TC_Port::strncasecmp(sBuffer, "PRI " , 4) !=0 && - TC_Port::strncasecmp(sBuffer, "DELETE " , 7) !=0 && - TC_Port::strncasecmp(sBuffer, "HEAD " ,5)) - { - throw runtime_error("[TC_HttpRequest::checkRequest] protocol not support, only support GET HEAD POST and OPTIONS "); - } - - - if(strstr(sBuffer, "\r\n\r\n") == NULL) - { - return false; - } - - _headLength = parseRequestHeader(sBuffer); - - bool bChunk = (getHeader("Transfer-Encoding") == "chunked"); - int iChunkSuffixLen = 0; - - if(bChunk) - { - string sTmp(sBuffer + _headLength, iLength - _headLength); - while(true) - { - string::size_type pos = sTmp.find("\r\n"); - if(pos == string::npos) - return false; - - //查找当前chunk的大小 - string sChunkSize = sTmp.substr(0, pos); - int iChunkSize = strtol(sChunkSize.c_str(), NULL, 16); - - iChunkSuffixLen = iChunkSuffixLen + sChunkSize.length(); - if (iChunkSize <= 0) - { - iChunkSuffixLen = iChunkSuffixLen + 4; - break; //所有chunk都接收完毕 - } - if(sTmp.length() >= pos + 2 + (size_t)iChunkSize + 2) //接收到一个完整的chunk了 - { - //获取一个chunk的内容 - _content += sTmp.substr(pos + 2, iChunkSize); - - //删除一个chunk - sTmp = sTmp.substr(pos + 2 + iChunkSize + 2); - iChunkSuffixLen = iChunkSuffixLen + 4; - } - else - { - //没有接收完整的chunk - return false; - } - - setContentLength(getContent().length()); - } - } - else - { - _content.assign((sBuffer + _headLength), iLength - _headLength); -// _content = sBuffer.substr(_headLength); - } - - return (getContentLength() + getHeadLength() + iChunkSuffixLen == iLength); -} - - -bool TC_HttpRequest::checkRequest(const char* sBuffer, size_t iLen) -{ - if(TC_Port::strncasecmp(sBuffer, "GET " ,4) !=0 && - TC_Port::strncasecmp(sBuffer, "POST " ,5) !=0 && - TC_Port::strncasecmp(sBuffer, "PUT " ,4) !=0 && - TC_Port::strncasecmp(sBuffer, "PATCH " ,6) !=0 && - TC_Port::strncasecmp(sBuffer, "OPTIONS " ,8) !=0 && - TC_Port::strncasecmp(sBuffer, "PRI " , 4) !=0 && - TC_Port::strncasecmp(sBuffer, "DELETE " , 7) !=0 && - TC_Port::strncasecmp(sBuffer, "HEAD " ,5)) - { - throw runtime_error("[TC_HttpRequest::checkRequest] protocol not support, only support GET HEAD POST PUT PATCH DELETE and OPTIONS "); - } - - const char *p = strstr(sBuffer, "\r\n\r\n"); - if( p == NULL) - { - return false; - } - - size_t pos = p - sBuffer; - - size_t iHeadLen= pos + 4; - - const char **ppChar = &sBuffer; - - bool bChunk = false; - - //找到\r\n\r\n之前的长度表示 - while(true) - { - size_t iMoveLen= (*ppChar) - sBuffer; - if ( iMoveLen >= iHeadLen ) - { - //MTT_ERRDAY << "parseHttp WARN: iMoveLen >= iLen" << "|" << iMoveLen << "|" <(TC_Common::trim(sLine.substr(15), " ")); - } - - if(len + pos + 4 <= iLen) - { - return true; - } - else - { - break; - - } - } - -/* - if(bChunk) - { - string sTmp = string(p + 4, iLen - iHeadLen); - while(true) - { - string::size_type pos = sTmp.find("\r\n"); - if(pos == string::npos) - { - return false; - } - - //查找当前chunk的大小 - string sChunkSize = sTmp.substr(0, pos); - int iChunkSize = strtol(sChunkSize.c_str(), NULL, 16); - - if(iChunkSize <= 0) - { - return true; //所有chunk都接收完毕 - } - if(sTmp.length() >= pos + 2 + (size_t)iChunkSize + 2) //接收到一个完整的chunk了 - { - //删除一个chunk - sTmp = sTmp.substr(pos + 2 + iChunkSize + 2); - } - else - { - return false; - } - } - } -*/ - if(bChunk) - { - int remain_len = iLen - iHeadLen; - int move_len = 0; - const char * pCur = p + 4; - while(true) - { - p = strstr(pCur , "\r\n"); - if( p == NULL ) - { - return false; - } - - //查找当前chunk的大小 - int iChunkSize = strtol(string(pCur, p - pCur).c_str(), NULL, 16); - if(iChunkSize <= 0) - { - return true; //所有chunk都接收完毕 - } - - move_len = (p - pCur) + 2 + iChunkSize + 2; - if( remain_len >= move_len ) //接收到一个完整的chunk了 - { - //移动到下一个chunk - remain_len -= move_len; - pCur = p + 2 + iChunkSize + 2; - } - else - { - return false; - } - } - } - - return false; -// throw TC_HttpRequest_Exception("[TC_HttpRequest::checkRequest] Content-Length not exists."); - -// return true; -} - - -size_t TC_HttpRequest::parseRequestHeader(const char* szBuffer) -{ - const char *szBuffer_copy = szBuffer; - const char **ppChar = &szBuffer; - - /* parse the first line and get status */ - string sLine = getLine(ppChar); - - string::size_type pos = sLine.find(" "); - if(pos == string::npos) - { - throw TC_HttpRequest_Exception("[TC_HttpRequest::parseRequestHeader] http request format error: " + sLine); - } - - string sMethod = TC_Common::trim(sLine.substr(0, pos)); - - //解析请求类型 - if(TC_Port::strncasecmp(sMethod.c_str(), "GET", 3) ==0) //if(sMethod == "GET") - { - _requestType = REQUEST_GET; - } - else if(TC_Port::strncasecmp(sMethod.c_str(), "POST", 4) ==0) //else if(sMethod == "POST") - { - _requestType = REQUEST_POST; - } - else if(TC_Port::strncasecmp(sMethod.c_str(), "PUT", 3) ==0) - { - _requestType = REQUEST_PUT; - } - else if(TC_Port::strncasecmp(sMethod.c_str(), "PATCH", 5) ==0) - { - _requestType = REQUEST_PATCH; - } - else if(TC_Port::strncasecmp(sMethod.c_str(), "OPTIONS", 7) ==0) //else if(sMethod == "OPTIONS") - { - _requestType = REQUEST_OPTIONS; - } - else if(TC_Port::strncasecmp(sMethod.c_str(), "HEAD", 4) == 0) - { - _requestType = REQUEST_HEAD; - } - else if(TC_Port::strncasecmp(sMethod.c_str(), "DELETE", 6) == 0) - { - _requestType = REQUEST_DELETE; - } - else - { - throw TC_HttpRequest_Exception("[TC_HttpRequest::parseRequestHeader] http request command error: " + sMethod); - } - - string::size_type pos1 = sLine.rfind(" "); - if(pos1 == string::npos || pos1 <= pos) - { - throw TC_HttpRequest_Exception("[TC_HttpRequest::parseRequestHeader] http request format error: " + sLine); - } - - //URL地址 - string sURL = TC_Common::trim(sLine.substr(pos+1, pos1 - pos)); - - //HTTP协议版本 - string sVersion = TC_Common::trim(sLine.substr(pos1 + 1)); - -// if (sVersion != "HTTP/1.1" || sVersion != "HTTP/1.0") - if (TC_Port::strncasecmp(sVersion.c_str(), "HTTP/1.1", 8) != 0 || TC_Port::strncasecmp(sVersion.c_str(), "HTTP/1.0", 8) != 0) - { - sVersion = "HTTP/1.1"; - } - - size_t n = parseHeader(*ppChar, _headers) - szBuffer_copy; - - if(TC_Port::strncasecmp(sURL.c_str(), "https://", 8) !=0 ) - { - if(TC_Port::strncasecmp(sURL.c_str(), "http://", 7) !=0 ) - { - sURL = "http://" + getHost() + sURL; - } - } - - parseURL(sURL); - - return n; -} - -void TC_HttpRequest::getHostPort(string &sDomain, uint32_t &iPort) -{ - sDomain = _httpURL.getDomain(); - - iPort = TC_Common::strto(_httpURL.getPort()); -} - -void TC_HttpRequest::setMethod(const char * sMethod) -{ - //解析请求类型 - if(TC_Port::strcasecmp(sMethod, "GET") ==0) //if(sMethod == "GET") - { - _requestType = REQUEST_GET; - } - else if(TC_Port::strcasecmp(sMethod, "POST") ==0) //else if(sMethod == "POST") - { - _requestType = REQUEST_POST; - } - else if(TC_Port::strcasecmp(sMethod, "PUT") ==0) - { - _requestType = REQUEST_PUT; - } - else if(TC_Port::strcasecmp(sMethod, "PATCH") ==0) - { - _requestType = REQUEST_PATCH; - } - else if(TC_Port::strcasecmp(sMethod, "OPTIONS") ==0) //else if(sMethod == "OPTIONS") - { - _requestType = REQUEST_OPTIONS; - } - else if(TC_Port::strcasecmp(sMethod, "HEAD") == 0) - { - _requestType = REQUEST_HEAD; - } - else if(TC_Port::strcasecmp(sMethod, "DELETE") == 0) - { - _requestType = REQUEST_DELETE; - } - else - { - throw TC_HttpRequest_Exception("[TC_HttpRequest::setMethod] http request command error: " + string(sMethod)); - } -} - -void TC_HttpRequest::setPath(const char *path) -{ - _httpURL._sPath = path; -} - -void TC_HttpRequest::setDomain(const char * sDomain) -{ - _httpURL._sDomain = sDomain; -} - -void TC_HttpRequest::setScheme(const char * sScheme) -{ - _httpURL._sScheme = sScheme; -} - -int TC_HttpRequest::doRequest(TC_TCPClient& tcpClient, TC_HttpResponse& stHttpRsp) -{ - //只支持短连接模式 - setConnection("close"); - - string sSendBuffer = encode(); - - int iRet = tcpClient.send(sSendBuffer.c_str(), sSendBuffer.length()); - if (iRet != TC_ClientSocket::EM_SUCCESS) - { - return iRet; - } - - stHttpRsp.reset(); - - string sBuffer; - - char* sTmpBuffer = new char[10240]; - size_t iRecvLen = 10240; - - while (true) - { - iRecvLen = 10240; - - iRet = tcpClient.recv(sTmpBuffer, iRecvLen); - - if (iRet == TC_ClientSocket::EM_SUCCESS) - sBuffer.append(sTmpBuffer, iRecvLen); - - switch (iRet) - { - case TC_ClientSocket::EM_SUCCESS: - if (stHttpRsp.incrementDecode(sBuffer)) - { - delete[]sTmpBuffer; - return TC_ClientSocket::EM_SUCCESS; - } - continue; - case TC_ClientSocket::EM_CLOSE: - delete[]sTmpBuffer; - stHttpRsp.incrementDecode(sBuffer); - return TC_ClientSocket::EM_SUCCESS; - default: - delete[]sTmpBuffer; - return iRet; - } - } - - assert(true); - - return 0; - -} -int TC_HttpRequest::doRequest(TC_HttpResponse &stHttpRsp, int iTimeout) -{ - //只支持短连接模式 - setConnection("close"); - - string sSendBuffer = encode(); - - string sHost; - uint32_t iPort; - - getHostPort(sHost, iPort); - - TC_TCPClient tcpClient; -// if (_client == NULL) - // { - // _client = new TC_TCPClient(); - // } - tcpClient.init(sHost, iPort, iTimeout); - - int iRet = tcpClient.send(sSendBuffer.c_str(), sSendBuffer.length()); - if(iRet != TC_ClientSocket::EM_SUCCESS) - { - return iRet; - } - - stHttpRsp.reset(); - - string sBuffer; - - char *sTmpBuffer = new char[10240]; - size_t iRecvLen = 10240; - - while(true) - { - iRecvLen = 10240; - - iRet = tcpClient.recv(sTmpBuffer, iRecvLen); - - if(iRet == TC_ClientSocket::EM_SUCCESS) - sBuffer.append(sTmpBuffer, iRecvLen); - - switch(iRet) - { - case TC_ClientSocket::EM_SUCCESS: - if(stHttpRsp.incrementDecode(sBuffer)) - { - delete []sTmpBuffer; - return TC_ClientSocket::EM_SUCCESS; - } - continue; - case TC_ClientSocket::EM_CLOSE: - delete []sTmpBuffer; - stHttpRsp.incrementDecode(sBuffer); - return TC_ClientSocket::EM_SUCCESS; - default: - delete []sTmpBuffer; - return iRet; - } - } - - assert(true); - - return 0; -} - -} - - +#include "util/tc_http.h" +#include "util/tc_port.h" +#include "util/tc_common.h" +#include "util/tc_clientsocket.h" +#include "util/tc_network_buffer.h" +#include + +namespace tars +{ + +const char* strnstr(const char* s1, const char* s2, int pos1) +{ + int l1, l2; + + l2 = strlen(s2); + if (!l2) + return (char *)s1; + l1 = strlen(s1); + + pos1 = (pos1 > l1)?l1:pos1; + + while (pos1 >= l2) { + pos1--; + if (!memcmp(s1, s2, l2)) + return (char *)s1; + s1++; + } + return NULL; +} + +unordered_map TC_Http::HEADER = { + {"GET", TC_HttpRequest::REQUEST_GET}, + {"POST", TC_HttpRequest::REQUEST_POST}, + {"PUT", TC_HttpRequest::REQUEST_PUT}, + {"PATCH", TC_HttpRequest::REQUEST_PATCH}, + {"OPTIONS", TC_HttpRequest::REQUEST_OPTIONS}, + {"PRI", TC_HttpRequest::REQUEST_PRI}, + {"DELETE", TC_HttpRequest::REQUEST_DELETE}, + {"HEAD", TC_HttpRequest::REQUEST_HEAD}, +}; + +unordered_map TC_Http::HEADER_REVERSE = { + {TC_HttpRequest::REQUEST_GET, "GET"}, + {TC_HttpRequest::REQUEST_POST, "POST"}, + {TC_HttpRequest::REQUEST_PUT, "PUT"}, + {TC_HttpRequest::REQUEST_PATCH, "PATCH"}, + {TC_HttpRequest::REQUEST_OPTIONS, "OPTIONS"}, + {TC_HttpRequest::REQUEST_PRI, "PRI"}, + {TC_HttpRequest::REQUEST_DELETE, "DELETE"}, + {TC_HttpRequest::REQUEST_HEAD, "HEAD"}, +}; + + +bool TC_Http::CmpCase::operator()(const string &s1, const string &s2) const +{ + if (TC_Port::strcasecmp(s1.c_str(), s2.c_str()) < 0) + { + return true; + } + else + { + return false; + } +} + +bool TC_URL::isValid() const +{ + return !_sURL.empty(); +} + +string TC_URL::getURL() const +{ + return _sURL; +} + +string TC_URL::type2String() const +{ + switch (_iURLType) + { + case HTTP: + return "http"; + case HTTPS: + return "https"; + case FTP: + return "ftp"; + } + + return "http"; +} + +string TC_URL::getDefaultPort() const +{ + switch (_iURLType) + { + case HTTP: + return "80"; + case HTTPS: + return "443"; + case FTP: + return "21"; + } + + return "80"; +} + +bool TC_URL::isDefaultPort() const +{ + return _sPort == getDefaultPort(); +} + +string TC_URL::toURL() +{ + _sURL.clear(); + + _sURL = _sScheme; + _sURL += "://"; + + if (!_sUser.empty()) + _sURL += _sUser; + + if (!_sUser.empty() && !_sPass.empty()) + { + _sURL += ":"; + _sURL += _sPass; + } + + if (!_sUser.empty()) + _sURL += "@"; + + _sURL += _sDomain; + + if (!isDefaultPort()) + { + _sURL += ":"; + _sURL += _sPort; + } + + _sURL += getRequest(); + + return _sURL; +} + +string TC_URL::getRequest() const +{ + string sURL; + + if (!_sPath.empty()) + sURL += _sPath; + + if (!_sQuery.empty()) + sURL += "?" + _sQuery; + + if (!_sRef.empty()) + sURL += "#" + _sRef; + + return sURL; +} + +bool TC_URL::parseURL(const string &originRequest) +{ +// string originRequest = TC_Common::trim(sURL, " "); + + if (originRequest.empty()) + { + return false; + } + + clear(); + + int iPos = 0; + + if (TC_Port::strncasecmp(originRequest.c_str(), "http://" , 7) == 0) + { + //http开头 + _iURLType = HTTP; + iPos = 7; + _sScheme = "http"; + } + else if (TC_Port::strncasecmp(originRequest.c_str(), "https://" , 8) == 0) + { + //https开头 + _iURLType = HTTPS; + iPos = 8; + _sScheme = "https"; + } + else if (TC_Port::strncasecmp(originRequest.c_str(), "ftp://", 6) == 0) + { + //ftps开头 + _iURLType = FTP; + iPos = 6; + _sScheme = "ftp"; + } + else + { + //默认用http + _iURLType = HTTP; + iPos = 0; + _sScheme = "http"; + } + + string::size_type index = originRequest.find("/", iPos); + string::size_type nQuestionIndex = originRequest.find("?", iPos); + string::size_type nNumbersignIndex = originRequest.find("#", iPos); + + string sUrlAuthority; + string sUrlPath; + + if (nQuestionIndex < index) + { + sUrlAuthority = originRequest.substr(iPos, nQuestionIndex - iPos); + + sUrlPath += '/'; + sUrlPath += originRequest.substr(nQuestionIndex); + } + else if (nNumbersignIndex < index) + { + sUrlAuthority = originRequest.substr(iPos, nNumbersignIndex - iPos); + + sUrlPath += '/'; + sUrlPath += originRequest.substr(nNumbersignIndex); + } + else + { + if (index == string::npos) + { + sUrlAuthority = originRequest.substr(iPos, index); + sUrlPath = ""; + } + else + { + sUrlAuthority = originRequest.substr(iPos, index - iPos); + sUrlPath = originRequest.substr(index); + } + } + + //////解析Authority + index = sUrlAuthority.find("@"); + if (index != string::npos) + { + _sUser = sUrlAuthority.substr(0, index); + _sDomain = sUrlAuthority.substr(index + 1); + } + else + { + _sDomain = sUrlAuthority; + } + + //////解析User:Pass + index = _sUser.find(":"); + if (index != string::npos) + { + _sPass = _sUser.substr(index + 1); + _sUser = _sUser.substr(0, index); + } + + //////解析Host:Port + index = _sDomain.find(":"); + if (index != string::npos) + { + _sPort = _sDomain.substr(index + 1); + + _sDomain = _sDomain.substr(0, index); + } + else + { + _sPort = getDefaultPort(); + } + + //////解析Path Query Ref + index = sUrlPath.find("?"); + if (index != string::npos) + { + _sPath = sUrlPath.substr(0, index); + _sQuery = sUrlPath.substr(index + 1); + + index = _sQuery.rfind("#"); + if (index != string::npos) + { + _sRef = _sQuery.substr(index + 1); + _sQuery = _sQuery.substr(0, index); + } + } + else + { + _sPath = sUrlPath; + _sQuery = ""; + + index = _sPath.rfind("#"); + if (index != string::npos) + { + _sRef = _sPath.substr(index + 1); + _sPath = _sPath.substr(0, index); + } + } + + if (_sPath.empty()) + { + _sPath = "/"; + } + + toURL(); + + //域名或者IP必须包含一个点 + if (_sDomain.find(".") == string::npos) + { + return false; + } + + return true; +} + +void TC_URL::specialize() +{ + //规整化路径 + /*string sUrlPath = simplePath(getPath()); + + _fragment["path"] = sUrlPath;*/ + _sPath = simplePath(getPath()); + + _sURL = toURL(); +} + +void TC_URL::clear() +{ + _sScheme = ""; + _sUser = ""; + _sPass = ""; + _sDomain = ""; + _sPort = ""; + _sPath = ""; + _sQuery = ""; + _sRef = ""; + + _sURL.clear(); +} + +string TC_URL::getScheme() const +{ + return _sScheme; +} + +string TC_URL::getUserName() const +{ + return _sUser; +} + +string TC_URL::getPassword() const +{ + return _sPass; +} + +string TC_URL::getDomain() const +{ + return _sDomain; +} + +string TC_URL::getPort() const +{ + return _sPort; +} + +string TC_URL::getPath() const +{ + return _sPath; +} + +string TC_URL::getQuery() const +{ + return _sQuery; +} + +string TC_URL::getRef() const +{ + return _sRef; +} + +string TC_URL::getRelativePath() const +{ + string sURL = getPath(); + + string::size_type pos; + + + pos = sURL.rfind("/"); + + if (pos == string::npos) + { + return "/"; + } + else + { + return sURL.substr(0, pos + 1); + } +} + +string TC_URL::getRootPath() const +{ + string sURL = _sScheme; + sURL += "://"; + + if (!_sUser.empty()) + sURL += _sUser; + + if (!_sUser.empty() && !_sPass.empty()) + { + sURL += ":"; + sURL += _sPass; + } + + if (!_sUser.empty()) + sURL += "@"; + + sURL += _sDomain; + + if (!isDefaultPort()) + { + sURL += ":"; + sURL += _sPort; + } + + sURL += "/"; + + return sURL; +} + +TC_URL TC_URL::buildWithRelativePath(const string &sRelativePath) const +{ + string sURL; + + if (!sRelativePath.empty() && sRelativePath[0] == '/') + { + //如果链接是用"/"开头的相对地址,那么应该用Host+相对地址 + sURL = sRelativePath.substr(1); + } + else if (sRelativePath[0] == '#') + { + //# + sURL = getPath().substr(1); + + if (!getQuery().empty()) + sURL += "?" + getQuery(); + + sURL += sRelativePath; + + } + else + { + //相对地址 + sURL = getRelativePath().substr(1) + sRelativePath; + } + + sURL = getRootPath() + simplePath("/" + sURL).substr(1); + + TC_URL url; + + url.parseURL(sURL); + + return url; +} + +string TC_URL::simplePath(const string &sPath) const +{ + //所有./都去掉 + size_t pos = 0; + string sNewPath = sPath; + + while (true) + { + size_t dotPos = sNewPath.find("./", pos); + + if (dotPos != string::npos) + { + if ((dotPos == 0) || (sNewPath.at(dotPos - 1) == '/')) + { + sNewPath.erase(dotPos, 2); + } + else + { + pos = dotPos + 2; + } + } + else + { + break; + } + } + + //如果路径是以.结尾的, 则.去掉 + if (((sNewPath.length() >= 2) && (sNewPath.substr(sNewPath.length() - 2) == "/.")) || (sNewPath == ".")) + { + sNewPath.erase(sNewPath.length() - 1); + } + + //处理/../的形式 + pos = 0; + size_t startPos = 0; + + while (1) + { + size_t slashDot = sNewPath.find("/../", pos); + + if (slashDot != string::npos) + { + if (0 == slashDot) + { + sNewPath.erase(0, 3); + continue; + } + + if ( (slashDot > 1) && (sNewPath.substr(slashDot - 2, 2) == "..") ) + { + pos = slashDot + 4; + continue; + } + + startPos = sNewPath.rfind('/', slashDot - 1); + + if (startPos == string::npos) startPos = 0; + + sNewPath.erase(startPos, slashDot + 4 - startPos - 1); + } + else + { + break; + } + } + + //处理/..结尾的情况 + if ((sNewPath.size() >= 3) && (sNewPath.substr(sNewPath.size() - 3, 3) == "/..")) + { + size_t slashDot = sNewPath.size() - 3; + if (!((slashDot > 1) && (sNewPath.substr(slashDot - 2, 2) == ".."))) + { + startPos = sNewPath.rfind ('/', slashDot - 1); + if (startPos == string::npos) startPos = 0; + sNewPath.erase (startPos + 1); + } + } + + return sNewPath; +} + +//////////////////////////////////////////////////////////////////// + +void TC_Http::setHeader(const string &sHeadName, const string &sHeadValue) +{ + //Set-Cookie和Cookie可以有多个头 + const char * pStr1 = "SET-COOKIE"; + const char * pStr2 = "COOKIE";//原则上COOKIE只有一个,担心有兼容性问题,保留 + if ((TC_Port::strcasecmp(sHeadName.c_str(), pStr1) != 0) && (TC_Port::strcasecmp(sHeadName.c_str(), pStr2) != 0)) + { + _headers.erase(sHeadName); + } + + _headers.insert(multimap::value_type(sHeadName, sHeadValue)); +} + +bool TC_Http::hasHeader(const char *sHeader) const +{ + http_header_type::const_iterator it = _headers.find(sHeader); + if (it == _headers.end()) + { + return false; + } + + return true; +} + +bool TC_Http::checkHeader(const char *sHeader, const char *value) const +{ + http_header_type::const_iterator it = _headers.find(sHeader); + if (it == _headers.end()) + { + return false; + } + + return TC_Port::strcasecmp(it->second.c_str(), value) == 0; +} + +string TC_Http::getHeader(const string& sHeader) const +{ + http_header_type::const_iterator it = _headers.find(sHeader); + if (it == _headers.end()) + { + return ""; + } + + return it->second; +} + +string TC_Http::getContentType() const +{ + return getHeader("Content-Type"); +} + +string TC_Http::getHost() const +{ + return getHeader("Host"); +} + +size_t TC_Http::getContentLength() const +{ + string s = getHeader("Content-Length"); + if (s.empty()) + { + return 0; + } + + return TC_Common::strto(s); +} + +string TC_Http::genHeader() const +{ + string sHttpHeader; + + for (http_header_type::const_iterator it = _headers.begin(); it != _headers.end(); ++it) + { + if (it->second != "") + { + sHttpHeader += it->first; + sHttpHeader += ": "; + sHttpHeader += it->second; + sHttpHeader += "\r\n"; + } + } + + return sHttpHeader; +} + +void TC_Http::genHeader(string &sHttpHeader) const +{ + for (http_header_type::const_iterator it = _headers.begin(); it != _headers.end(); ++it) + { + if (it->second != "") + { + sHttpHeader += it->first; + sHttpHeader += ": "; + sHttpHeader += it->second; + sHttpHeader += "\r\n"; + } + } +} + +vector TC_Http::getHeaderMulti(const string &sHeadName) const +{ + vector v; + + http_header_type::const_iterator itEnd = _headers.end(); + + for ( http_header_type::const_iterator it = _headers.begin(); it != itEnd; ++it) + { + if (TC_Port::strcasecmp(it->first.c_str(), sHeadName.c_str()) == 0) + { + v.push_back(it->second); + } + } + + return v; +} + +void TC_Http::reset() +{ + _headers.clear(); + _version.clear(); + _headLength = 0; + _content.clear(); + _bIsChunked = false; +} + +void TC_Http::getHeaders(map &header) +{ + for(auto it = _headers.begin(); it != _headers.end(); ++it) + { + header.insert(map::value_type(it->first, it->second)); + } +} + +/********************* TC_HttpCookie ***********************/ + +bool TC_HttpCookie::matchDomain(const string &sCookieDomain, const string &sDomain) +{ + string sCookieDomainNew = TC_Common::lower(sCookieDomain); + + //没有点的自动加点 + if (sCookieDomainNew.find(".") != 0) + { + sCookieDomainNew = "." + sCookieDomainNew; + } + + string::size_type pos = sCookieDomainNew.find("."); + + //sCookieDomain串至少有两个点 + if (pos == string::npos || (pos == 0 && sCookieDomainNew.rfind(".") == 0)) + { + return false; + } + + string sLowerDomain = TC_Common::lower(sDomain); + + //后边是子域名 + if (sDomain.length() >= sCookieDomainNew.length() && + sLowerDomain.compare(sDomain.length() - sCookieDomainNew.length(), sCookieDomainNew.length(), sCookieDomainNew) == 0) + { + return true; + } + + //去掉.相等 + if (sLowerDomain == sCookieDomainNew.substr(1)) + { + return true; + } + + return false; +} + +size_t TC_HttpCookie::matchPath(const string &sCookiePath, const string &sPath) +{ + if (sCookiePath.empty() || sPath.empty()) return 0; + + //都在最后加/再匹配 + string sCookiePath1 = (sCookiePath.at(sCookiePath.length() - 1) == '/') ? sCookiePath : sCookiePath + "/"; + + string sPath1 = (sPath.at(sPath.length() - 1) == '/') ? sPath : sPath + "/"; + + if (sPath1.find(sCookiePath1) == 0) + { + return sCookiePath1.length(); + } + + return 0; +} + +void TC_HttpCookie::clear() +{ + _cookies.clear(); +} + +bool TC_HttpCookie::fixDomain(const string &sDomain, string &sFixDomain) +{ + if (sDomain.empty()) + { + return false; + } + + sFixDomain = sDomain; + + //自动加. + if (sDomain.at(0) != '.') + { + sFixDomain = "." + sDomain; + } + + //domain至少两段 + if (sFixDomain.find(".") == sFixDomain.rfind(".")) + return false; + + return true; +} + +void TC_HttpCookie::addCookie(const Cookie &cookie, list &cookies) +{ + string sDomain; + + Cookie cookieNew = cookie; + + if (!fixDomain(cookieNew._domain, sDomain)) + return; + + cookieNew._domain = sDomain; + + if (cookieNew._path.empty()) + return; + + list::iterator it = cookies.begin(); + + string sName; + if (cookieNew._data.size() >= 1) + { + sName = cookieNew._data.begin()->first; + } + + while (it != cookies.end()) + { + //检查Cookie是否过期 + if (isCookieExpires(*it)) + { + cookies.erase(it++); + } + else if (TC_Port::strcasecmp(it->_domain.c_str(), cookieNew._domain.c_str()) == 0 + && strcmp(it->_path.c_str(), cookieNew._path.c_str()) == 0 + && it->_isSecure == cookieNew._isSecure) + { + if (it->_expires == cookieNew._expires) + { + //domain/path/expires都匹配的情况下, 覆盖老cookie的数据 + cookieNew._data.insert(it->_data.begin(), it->_data.end()); + + cookies.erase(it++); + } + else + { + //超时间不一样,但存在同样的key,需删除 + if (it->_data.find(sName) != it->_data.end()) + { + it->_data.erase(sName); + } + ++it; + } + } + else + { + ++it; + } + } + + cookies.push_back(cookieNew); +} + +void TC_HttpCookie::addCookie(const Cookie &cookie) +{ + addCookie(cookie, _cookies); +} + +void TC_HttpCookie::addCookie(const list &cookie) +{ + list::const_iterator it = cookie.begin(); + + while (it != cookie.end()) + { + addCookie(*it); + + ++it; + } +} + +void TC_HttpCookie::addCookie(const string &sRspURL, const vector &vCookies) +{ + TC_URL cURL; + + cURL.parseURL(sRspURL); + + string sRspURLDomain = TC_Common::lower(cURL.getDomain()); + + string sRspURLPath = cURL.getPath(); + + for (size_t i = 0; i < vCookies.size(); i++) + { + //处理一行SetCookie + vector v = TC_Common::sepstr(vCookies[i], ";"); + + Cookie cookie; + + cookie._isSecure = false; + cookie._expires = 0; + + //解析Cookie数据 + for (size_t j = 0; j < v.size(); ++j) + { + string::size_type index = v[j].find("="); + + string name; + + string value; + + if (index != string::npos) + { + name = TC_Common::trim(v[j].substr(0, index), " "); + + value = TC_Common::trim(v[j].substr(index + 1)); + } + else + { + name = TC_Common::trim(v[j]); + } + if (TC_Port::strcasecmp(name.c_str(), "secure") == 0) + { + cookie._isSecure = true; + } + else if (TC_Port::strcasecmp(name.c_str(), "expires") == 0) + { + struct tm stTm; + //兼容时间格式 + //expires=Mon, 09-May-41 08:39:32 GMT + //expires=Thu, 01-Jan-1970 01:00:00 GMT + value = TC_Common::replace(value, "-", " "); + if (value.length() == 27 && value.at(11) == ' ' && value.at(14) == ' ') + { + int year = TC_Common::strto (value.substr(12, 2)); + if (year >= 69 && year <= 99) + value = value.substr(0, 12) + "19" + value.substr(12); + else + value = value.substr(0, 12) + "20" + value.substr(12); + } + + TC_Common::strgmt2tm(value, stTm); + + cookie._expires = TC_Port::timegm(&stTm); + } + else if (TC_Port::strcasecmp(name.c_str(), "path") == 0) + { + cookie._path = value; + } + else if (TC_Port::strcasecmp(name.c_str(), "domain") == 0) + { + cookie._domain = value; + } + else if (TC_Port::strcasecmp(name.c_str(), "httponly") == 0) + { + //TODO + //cookie._isHttpOnly = true; + } + else + cookie._data.insert(http_cookie_data::value_type(name, value)); + } + + ///修正和匹配domain///////////////////////////////////////// + if (cookie._domain.empty()) + cookie._domain = sRspURLDomain; + + if (!fixDomain(cookie._domain, cookie._domain)) + continue; + + //匹配域名 + if (!matchDomain(cookie._domain, sRspURLDomain)) + continue; + + //修改和匹配path///////////////////////////// + if (cookie._path.empty()) + { + string sCookiePath; + + //缺省是全路径 + string sRequest = sRspURLPath; + + string::size_type pos = sRequest.rfind("/"); + + if (pos == string::npos) + sCookiePath = "/"; + else + sCookiePath = sRequest.substr(0, pos + 1); + + cookie._path = sCookiePath; + } + + //URL在Path范围内,Cookie 有效 + if (!matchPath(cookie._path, sRspURLPath)) + continue; + + //添加Cookie + addCookie(cookie); + } +} + +bool TC_HttpCookie::isCookieExpires(const Cookie &cookie) const +{ + //过期了 + if (cookie._expires != 0 && cookie._expires < time(NULL)) + return true; + + return false; +} + +size_t TC_HttpCookie::isCookieMatch(const Cookie &cookie, const TC_URL &tURL) const +{ + //域名没有匹配 + if (!matchDomain(cookie._domain, tURL.getDomain())) + return 0; + + //路径没有匹配 + size_t len = matchPath(cookie._path, tURL.getPath()); + if (len == 0) + return 0; + + //安全的cookie,不安全的URL + if (cookie._isSecure && (tURL.getType() != TC_URL::HTTPS)) + return 0; + + return len; +} + +void TC_HttpCookie::getCookieForURL(const string &sReqURL, list &cookies) +{ + TC_URL tURL; + + tURL.parseURL(sReqURL); + + cookies.clear(); + + list::iterator it = _cookies.begin(); + + while (it != _cookies.end()) + { + //检查Cookie是否过期 + if (isCookieExpires(*it)) + { + _cookies.erase(it++); + continue; + } + + size_t len = isCookieMatch(*it, tURL); + if (len == 0) + { + ++it; + continue; + } + + cookies.push_back(*it); + + ++it; + } +} + +void TC_HttpCookie::getCookieForURL(const string &sReqURL, string &sCookie) +{ + list cookies; + + sCookie.clear(); + + getCookieForURL(sReqURL, cookies); + + list::iterator it = cookies.begin(); + while (it != cookies.end()) + { + http_cookie_data::iterator itd = it->_data.begin(); + + while (itd != it->_data.end()) + { + //被删除的cookie不输出 + if (itd->first != "" && itd->second != "" && TC_Common::lower(itd->second) != "null" + && TC_Common::lower(itd->second) != "deleted") + sCookie += itd->first + "=" + itd->second + "; "; + + ++itd; + } + + ++it; + } + + //去掉末尾的 "; " + if (sCookie.length() >= 2) + sCookie = sCookie.substr(0, sCookie.length() - 2); +} + +list TC_HttpCookie::getSerializeCookie(time_t t) +{ + list cookies; + + list::iterator it = _cookies.begin(); + + while (it != _cookies.end()) + { + if (isCookieExpires(*it)) + { + _cookies.erase(it++); + continue; + } + else if (it->_expires != 0) //非当前会话的 + { + cookies.push_back(*it); + + ++it; + } + else + ++it; + } + + return cookies; +} + +const list & TC_HttpCookie::getAllCookie() +{ + deleteExpires(time(NULL)); + + return _cookies; +} + +void TC_HttpCookie::deleteExpires(time_t t, bool bErase) +{ + list::iterator it = _cookies.begin(); + + while (it != _cookies.end()) + { + if (bErase && it->_expires == 0) + { + _cookies.erase(it++); + continue; + } + else if (isCookieExpires(*it)) + { + _cookies.erase(it++); + continue; + } + else + ++it; + } +} + +/********************* TC_HttpResponse ***********************/ +void TC_HttpResponse::reset() +{ + TC_Http::reset(); + + _status = 200; + _about = "OK"; + _version = "HTTP/1.1"; + + _iTmpContentLength = 0; + + _iRecvContentLength = 0; +} + +vector TC_HttpResponse::getSetCookie() const +{ + return getHeaderMulti("Set-Cookie"); +} + +void TC_HttpResponse::addContent(const string &sBuffer) +{ + _content += sBuffer; + + _iRecvContentLength += sBuffer.length(); +} + +void TC_HttpResponse::addContent(const char *buffer, size_t length) +{ + _content.append(buffer, length); + + _iRecvContentLength += length; +} + +size_t TC_HttpResponse::parseResponseHeaderString(const char *beginIt, const char *headerIt) +{ + auto it = strnstr(beginIt, "\r\n", headerIt - beginIt); + + assert(it != NULL); + + auto f1 = strnstr(beginIt, " ", it - beginIt); + if(f1 == NULL) + { + throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response parse version format error : " + string(beginIt, headerIt - beginIt)); + } + + auto f2 = strnstr(f1 + 1, " ", it - (f1 + 1)); + if(f1 == NULL) + { + throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response parse status format error : " + string(beginIt, headerIt - beginIt)); + } + + _headerLine = string(beginIt, it - beginIt); + + if(TC_Port::strncasecmp(_headerLine.c_str(), "HTTP/", 5) != 0) + { + throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response version is not start with 'HTTP/' : " + _headerLine); + } + + _version = string(beginIt, f1 - beginIt); + + _status = TC_Common::strto(string(f1 + 1, f2)); + + _about = string(f2 + 1, it); + + return parseHeaderString(beginIt, headerIt, _headers); +} + +bool TC_HttpResponse::incrementDecode(TC_NetWorkBuffer &buff) +{ + if(buff.empty()) + return false; + //解析头部 + if (_headLength == 0) + { + //至少把header合并成一个buff + buff.mergeBuffers(); + + auto data = buff.getBufferPointer(); + + const char * p = strnstr(data.first, "\r\n\r\n", data.second); + if(p == NULL) + { + return false; + } + + _headLength = p - data.first + 4; + + _iTmpContentLength = parseResponseHeaderString(data.first, data.first + data.second); + + //304的返回码中头里本来就没有Content-Length,也不会有数据体,头收全了就是真正的收全了 + if ( (204 == _status) || (304 == _status) ) + { + return true; + } + + buff.moveHeader(_headLength); + + //重定向就认为成功了 + if ((_status == 301 || _status == 302) && hasHeader("Location")) + { + return true; + } + + //是否是chunk编码 + _bIsChunked = checkHeader("Transfer-Encoding", "chunked"); + if(_bIsChunked) { + //删除头部里面 + eraseHeader("Transfer-Encoding"); + } + } + + if (_bIsChunked) + { + while (true) + { + const static string sep = "\r\n"; + + auto sit = std::search(buff.begin(), buff.end(), sep.c_str(), sep.c_str() + sep.size()); + + if (sit == buff.end()) + { + return false; + } + + string header = buff.iteratorToIterator(buff.begin(), sit); + + int iChunkSize = strtol(header.c_str(), NULL, 16); + + if (iChunkSize <= 0) + { + break; //所有chunk都接收完毕 + } + + if (buff.getBufferLength() < header.size() + 2 + (size_t)iChunkSize + 2) + { + //没有接收完整的chunk + return false; + } + + //接收到一个完整的chunk了 + buff.moveHeader(header.size() + 2); + addContent(buff.getHeader(iChunkSize)); + + //删除一个chunk + buff.moveHeader(iChunkSize + 2); + } + + buff.clearBuffers(); + + //接收到buffer长度设置好 + setContentLength(_iRecvContentLength); + + return true; + } + else + { + if (_iTmpContentLength == 0) + { + //header长度为0, 但是有body数据 + addContent(buff.getBuffersString()); + + buff.clearBuffers(); + + if(_iRecvContentLength > 0) { + setContentLength(_iRecvContentLength); + } + + return true; + } + else if (_iTmpContentLength == (size_t) - 1) + { + //304的返回码中头没有Content-Length,不会有数据体 + if (_status == 304 || _status == 302) + { + return true; + } + + //header中没长度, 但是有body数据 + addContent(buff.getBuffersString()); + + buff.clearBuffers(); + + if(_iRecvContentLength > 0) { + setContentLength(_iRecvContentLength); + } + + return true; + } + else + { + //头部有长度, 接收到长度大于头部为止 + addContent(buff.getBuffersString()); + + buff.clearBuffers(); + + //头部的长度小于接收的内容, 还需要继续增加解析后续的buffer + if (_iTmpContentLength > _iRecvContentLength) + return false; + + return true; + } + } + + return true; +} + +bool TC_HttpResponse::decode(const string &sBuffer) +{ + return decode(sBuffer.c_str(), sBuffer.length()); +} + +bool TC_HttpResponse::decode(const char *sBuffer, size_t iLength) +{ + assert(sBuffer != NULL); + + const char *pHeader = sBuffer; + + const char *p = strnstr(sBuffer, "\r\n\r\n", iLength); + if ( p == NULL) + { + return false; + } + + //解析头部 + _iTmpContentLength = parseResponseHeaderString(sBuffer, p + 2); + + //304的返回码中头里本来就没有Content-Length,也不会有数据体,头收全了就是真正的收全了 + if ( (204 == _status) || (304 == _status) ) + { + return true; + } + + _headLength = p - sBuffer + 4; + + sBuffer += _headLength; + + //重定向就认为成功了 + if ((_status == 301 || _status == 302) && hasHeader("Location")) + { + return true; + } + + //是否是chunk编码 + _bIsChunked = checkHeader("Transfer-Encoding", "chunked"); + if(_bIsChunked) { + //删除头部里面 + eraseHeader("Transfer-Encoding"); + } + +// _bIsChunked = (getHeader("Transfer-Encoding") == "chunked"); + + //删除头部里面 +// eraseHeader("Transfer-Encoding"); + + if (_bIsChunked) + { + while (true) + { + p = strnstr(sBuffer, "\r\n", iLength - (sBuffer - pHeader)); + if (p == NULL) + return false; + + size_t pos = p - sBuffer; + + //查找当前chunk的大小 + string sChunkSize; + sChunkSize.insert(sChunkSize.end(), sBuffer, p); + int iChunkSize = strtol(sChunkSize.c_str(), NULL, 16); + + if (iChunkSize <= 0) break; //所有chunk都接收完毕 + + if (strlen(sBuffer) < pos + 2 + (size_t)iChunkSize + 2) + { + //没有接收完整的chunk + return false; + } + + //接收到一个完整的chunk了 + addContent(p + 2, iChunkSize); + + //删除一个chunk + sBuffer += pos + 2 + iChunkSize + 2; + } + + //接收到buffer长度设置好 + setContentLength(_iRecvContentLength); + + return true; + } + else + { + if (_iTmpContentLength == 0) + { + //header长度为0, 但是有body数据 + addContent(sBuffer); + + setContentLength(_iRecvContentLength); + + return true; + } + else if (_iTmpContentLength == (size_t) - 1) + { + //304的返回码中头没有Content-Length,不会有数据体 + if (_status == 304 || _status == 302) + { + return true; + } + + //header中没长度, 但是有body数据 + addContent(sBuffer); + + setContentLength(_iRecvContentLength); + } + else + { + //头部有长度, 接收到长度大于头部为止 + addContent(sBuffer); + + //头部的长度小于接收的内容, 还需要继续增加解析后续的buffer + if (_iTmpContentLength <= _iRecvContentLength) + return true; + } + } + + //body内容长度为0或者没有content-length 且 非chunk模式, 则认为包收全了, 直接返回 + if ((_iTmpContentLength == 0 || _iTmpContentLength == (size_t) - 1) && !_bIsChunked) + return true; + + return (getContentLength() + getHeadLength() <= iLength); +} + +string TC_HttpResponse::encode() const +{ + string sRet; + sRet.reserve(128); + + sRet += _version; + sRet += " "; + sRet += TC_Common::tostr(_status); + sRet += " "; + sRet += _about; + sRet += "\r\n"; + genHeader(sRet); + sRet += "\r\n"; + sRet += _content; + + return sRet; +} + +void TC_HttpResponse::encode(vector &buffer) const +{ + buffer.clear(); + + string s = encode(); + + buffer.resize(s.length()); + memcpy(buffer.data(), s.c_str(), s.length()); +} + +void TC_HttpResponse::setResponse(int status, const string& about, const string& body) +{ + _status = status; + _about = about; + _content = body; + + /*stringstream os; + + os << _version << " " << _status << " " << _about; + + _headerLine = os.str();*/ + _headerLine = ""; + _headerLine += _version; + _headerLine += " "; + _headerLine += TC_Common::tostr(_status); + _headerLine += " "; + _headerLine += _about; + + setHeader("Content-Length", TC_Common::tostr(_content.length())); +} + +void TC_HttpResponse::setResponse(int status, const string& about, const char *sBuffer, size_t iLength) +{ + _status = status; + _about = about; + + /*stringstream os; + + os << _version << " " << _status << " " << _about; + + _headerLine = os.str();*/ + _headerLine = ""; + _headerLine += _version; + _headerLine += " "; + _headerLine += TC_Common::tostr(_status); + _headerLine += " "; + _headerLine += _about; + + if (sBuffer != NULL && iLength > 0) + { + _content.assign(sBuffer, iLength); + } + else + { + _content.clear(); + } + + + setHeader("Content-Length", TC_Common::tostr(_content.length())); +} + +void TC_HttpResponse::setResponse(const char *sBuffer, size_t iLength) +{ + setResponse(200, "OK", sBuffer, iLength); +} + +/********************* TC_HttpRequest ***********************/ + +void TC_HttpRequest::reset() +{ + TC_Http::reset(); + + _httpURL.clear(); +} + +vector TC_HttpRequest::getCookie() +{ + vector v; + + http_header_type::const_iterator itEnd = _headers.end(); + + for ( http_header_type::const_iterator it = _headers.begin(); it != itEnd; ++it) + { + if (it->first == "Cookie") + { + v.push_back(it->second); + } + } + + return v; +} + +void TC_HttpRequest::parseURL(const string& sUrl) +{ + _httpURL.parseURL(sUrl); + + //设置Host + if (!hasHeader("Host")) + { + string sPort = _httpURL.isDefaultPort() ? "" : ":" + _httpURL.getPort(); + + //缺省端口可以不用放进去 + setHost(_httpURL.getDomain() + sPort); + } +} + +void TC_HttpRequest::setRequest(const string& method, const string &sUrl, const std::string& body, bool bNewCreateHost) +{ + if (TC_Port::strncasecmp(method.c_str(), "GET", 3) == 0) + setGetRequest(sUrl, bNewCreateHost); + else if (TC_Port::strncasecmp(method.c_str(), "HEAD", 4) == 0) + setHeadRequest(sUrl, bNewCreateHost); + else if (TC_Port::strncasecmp(method.c_str(), "POST", 4) == 0) + setPostRequest(sUrl, body, bNewCreateHost); + else if (TC_Port::strncasecmp(method.c_str(), "PUT", 3) == 0) + setPutRequest(sUrl, body, bNewCreateHost); + else if (TC_Port::strncasecmp(method.c_str(), "DELETE", 6) == 0) + setDeleteRequest(sUrl, body, bNewCreateHost); + else if (TC_Port::strncasecmp(method.c_str(), "PATH", 5) == 0) + setPatchRequest(sUrl, body, bNewCreateHost); +} + +void TC_HttpRequest::setGetRequest(const string &sUrl, bool bNewCreateHost) +{ + if (bNewCreateHost) + { + eraseHeader("Host"); + } + + parseURL(sUrl); + + _requestType = REQUEST_GET; + + _content = ""; + + eraseHeader("Content-Length"); +} + +void TC_HttpRequest::setHeadRequest(const string &sUrl, bool bNewCreateHost) +{ + if (bNewCreateHost) + { + eraseHeader("Host"); + } + + parseURL(sUrl); + + _requestType = REQUEST_HEAD; + + _content = ""; + + eraseHeader("Content-Length"); +} + +void TC_HttpRequest::setPostRequest(const string &sUrl, const string &sPostBody, bool bNewCreateHost) +{ + if (bNewCreateHost) + { + eraseHeader("Host"); + } + + parseURL(sUrl); + + _requestType = REQUEST_POST; + + _content = sPostBody; + + setHeader("Content-Length", TC_Common::tostr(_content.length())); +} + +void TC_HttpRequest::setOptionsRequest(const string &sUrl, bool bNewCreateHost) +{ + if (bNewCreateHost) + { + eraseHeader("Host"); + } + + parseURL(sUrl); + + _requestType = REQUEST_OPTIONS; + + _content = ""; + + eraseHeader("Content-Length"); +} + +void TC_HttpRequest::setPostRequest(const string &sUrl, const char *sBuffer, size_t iLength, bool bNewCreateHost) +{ + assert(sBuffer != NULL); + + if (bNewCreateHost) + { + eraseHeader("Host"); + } + + parseURL(sUrl); + + _requestType = REQUEST_POST; + + if (iLength > 0) + { + _content.assign(sBuffer, iLength); + } + else + { + _content.clear(); + } + + setHeader("Content-Length", TC_Common::tostr(_content.length())); +} + + +void TC_HttpRequest::setPutRequest(const string &sUrl, const string &sPostBody, bool bNewCreateHost ) +{ + if(bNewCreateHost) + { + eraseHeader("Host"); + } + + parseURL(sUrl); + + _requestType = REQUEST_PUT; + + _content = sPostBody; + + setHeader("Content-Length", TC_Common::tostr(_content.length())); +} + +void TC_HttpRequest::setPatchRequest(const string &sUrl, const string &sPostBody, bool bNewCreateHost ) +{ + if(bNewCreateHost) + { + eraseHeader("Host"); + } + + parseURL(sUrl); + + _requestType = REQUEST_PATCH; + + _content = sPostBody; + + setHeader("Content-Length", TC_Common::tostr(_content.length())); +} + + +void TC_HttpRequest::setDeleteRequest(const string &sUrl, const string &sPostBody, bool bNewCreateHost ) +{ + if(bNewCreateHost) + { + eraseHeader("Host"); + } + + parseURL(sUrl); + + _requestType = REQUEST_DELETE; + + _content = sPostBody; + + setHeader("Content-Length", TC_Common::tostr(_content.length())); + +} + +string TC_HttpRequest::encode() +{ + string sRet; + sRet.reserve(128); + if(_requestType == REQUEST_GET || _requestType == REQUEST_OPTIONS || _requestType == REQUEST_HEAD) + { + sRet += getMethod();//(_requestType); + sRet += " "; + sRet += _httpURL.getRequest(); + sRet += " HTTP/1.1\r\n"; + genHeader(sRet); + sRet += "\r\n"; + } + else if(_requestType == REQUEST_POST || _requestType == REQUEST_PUT || _requestType == REQUEST_PATCH || _requestType == REQUEST_DELETE) + { + setContentLength(_content.length()); + sRet += getMethod();//requestType2str(_requestType); + sRet += " "; + sRet += _httpURL.getRequest(); + sRet += " HTTP/1.1\r\n"; + genHeader(sRet); + sRet += "\r\n"; + sRet += _content; + } + return sRet; +} + +void TC_HttpRequest::encode(vector &sRet) +{ + string s = encode(); + sRet.resize(s.length()); + memcpy(sRet.data(), s.c_str(), s.length()); +} + +void TC_HttpRequest::encode(TC_NetWorkBuffer &buff) +{ + buff.addBuffer(std::move(encode())); +} + +bool TC_HttpRequest::decode(const string &sBuffer) +{ + return decode(sBuffer.c_str(), sBuffer.length()); +} + +bool TC_HttpRequest::decode(const vector &sBuffer) +{ + return decode(sBuffer.data(), sBuffer.size()); +} + +bool TC_HttpRequest::decode(const char *sBuffer, size_t iLength) +{ + assert(sBuffer != NULL); + + const char *p = strnstr(sBuffer, " ", 10); + if(p == NULL) + { + throw runtime_error("[TC_HttpRequest::decode] http protocol parse error"); + } + + auto it = TC_Http::HEADER.find(string(sBuffer, p - sBuffer)); + if(it == TC_Http::HEADER.end()) + { + throw runtime_error("[TC_HttpRequest::decode] protocol not support "); + } + + p = strnstr(sBuffer, "\r\n\r\n", iLength); + if (p == NULL) + { + return false; + } + + _requestType = it->second; + + parseRequestHeader(sBuffer, p); + + _headLength = p - sBuffer + 4; + + bool bChunk = checkHeader("Transfer-Encoding", "chunked"); //(getHeader("Transfer-Encoding") == "chunked"); + + int iChunkSuffixLen = 0; + + if (bChunk) + { + p = sBuffer + _headLength; + while (true) + { + const char *pos = strnstr(p, "\r\n", iLength - (p - sBuffer)); + +// const char *pos = strstr(p, "\r\n"); + if (pos == NULL) + return false; + + //查找当前chunk的大小 + string sChunkSize(p, pos - p); + int iChunkSize = strtol(sChunkSize.c_str(), NULL, 16); + + iChunkSuffixLen = iChunkSuffixLen + sChunkSize.length(); + if (iChunkSize <= 0) + { + iChunkSuffixLen = iChunkSuffixLen + 4; + break; //所有chunk都接收完毕 + } + if ((sBuffer+iLength-p) >= (pos - p) + 2 + iChunkSize + 2) //接收到一个完整的chunk了 + { + //获取一个chunk的内容 + _content.append(pos + 2, iChunkSize); + + //删除一个chunk + p = pos + 2 + iChunkSize + 2; + iChunkSuffixLen = iChunkSuffixLen + 4; + } + else + { + //没有接收完整的chunk + return false; + } + + setContentLength(getContent().length()); + } + } + else + { + _content.assign((sBuffer + _headLength), iLength - _headLength); + } + + return (getContentLength() + getHeadLength() + iChunkSuffixLen == iLength); +} + +bool TC_HttpRequest::checkRequest(TC_NetWorkBuffer &buff) +{ + buff.mergeBuffers(); + + return checkRequest(buff.getBufferPointer().first, buff.getBufferLength()); +} + +bool TC_HttpRequest::checkRequest(const char* sBuffer, size_t iLen) +{ + if(iLen < 10) + return false; + + const char *p = strnstr(sBuffer, " ", 10); + if(p == NULL) + { + throw runtime_error("[TC_HttpRequest::checkRequest] http protocol parse error"); + } + + auto it = TC_Http::HEADER.find(string(sBuffer, p - sBuffer)); + if(it == TC_Http::HEADER.end()) + { + throw runtime_error("[TC_HttpRequest::checkRequest] protocol not support: " + string(sBuffer, 8)); + } + + const char *header = strnstr(sBuffer, "\r\n\r\n", iLen); + if ( header == NULL) + { + return false; + } + + size_t pos = header - sBuffer; + + size_t iHeadLen = pos + 4; + + p = strnstr(sBuffer, "\r\n", iHeadLen); + if(p == NULL) + { + //first line + return false; + } + + p += 2; + + bool bChunk = false; + + size_t len = 0; + + //找到\r\n\r\n之前的长度表示 + while (true) + { + size_t iMoveLen = p - sBuffer; + if ( iMoveLen >= iHeadLen ) + { + break; + } + + const char *line = p; +// const char *lineEnd = strnstr(line, "\r\n", iLen - (line - sBuffer)); + + const char *lineEnd = strstr(line, "\r\n"); + if (lineEnd != NULL) + { + p = lineEnd + 2; + + if (TC_Port::strncasecmp(line, "Transfer-Encoding:", 18) == 0) + { + string chunked = TC_Common::trim(string(line + 18, lineEnd)); + bChunk = (chunked == "chunked"); + if (bChunk) break; + } + else if (TC_Port::strncasecmp(line, "Content-Length:", 15) != 0) + { + continue; + } + else + { + len = TC_Common::strto(TC_Common::trim(string(line + 15, lineEnd), " ")); + } + } + } + + if (bChunk) + { + int remain_len = iLen - iHeadLen; + int move_len = 0; + const char * pCur = header + 4; + while (true) + { + p = strnstr(pCur, "\r\n", remain_len); + +// p = strstr(pCur , "\r\n"); + if ( p == NULL ) + { + return false; + } + + //查找当前chunk的大小 + int iChunkSize = strtol(string(pCur, p - pCur).c_str(), NULL, 16); + if (iChunkSize <= 0) + { + return true; //所有chunk都接收完毕 + } + + move_len = (p - pCur) + 2 + iChunkSize + 2; + if ( remain_len >= move_len ) //接收到一个完整的chunk了 + { + //移动到下一个chunk + remain_len -= move_len; + pCur = p + 2 + iChunkSize + 2; + } + else + { + return false; + } + } + } + else if (len + pos + 4 <= iLen) + { + return true; + } + + return false; +} + +size_t TC_Http::parseHeaderString(const char *beginIt, const char *headerIt, TC_Http::http_header_type &sHeader) +{ + size_t contentLength = -1; + + sHeader.clear(); + + bool first = true; + auto lineStartIt= beginIt; + bool isLastLine = false; + + while (true) + { + auto it = strnstr(lineStartIt, "\r\n", headerIt - lineStartIt); + if(it == NULL) + { + it = headerIt; + isLastLine = true; + } + + //first line ignore + if(!first) + { + auto itF = strnstr(lineStartIt, ":", it - lineStartIt); + if (itF != NULL) + { + while(*lineStartIt == ' ') + ++lineStartIt; + + const char *s = itF; + while(*s == ' ') + --s; + + string name(lineStartIt, s - lineStartIt); + + ++itF; + while(*itF == ' ') + ++itF; + + s = it; + while(*s == ' ') + --s; + + string value(itF, s-itF); + + if (TC_Port::strncasecmp(name.c_str(), "Content-Length", 14) == 0) + { + contentLength = TC_Common::strto(value); + } + + if(name.empty()) + { + assert(false); + } + sHeader.insert(multimap::value_type(std::move(name), std::move(value))); + } + } + else + { + first = false; + } + + if (isLastLine) + { + break; + } + + lineStartIt = it + 2;//sep.size(); + } + + return contentLength; +} + +void TC_HttpRequest::parseRequestHeader(const char* szBuffer, const char *header) +{ + const char *p = strstr(szBuffer, "\r\n"); + + assert(p != NULL); + + auto f1 = strnstr(szBuffer, " ", p - szBuffer); + if (f1 == p) + { + throw TC_HttpRequest_Exception("[TC_HttpRequest::parseRequestHeader] http request format error: " + string(szBuffer, p - szBuffer)); + } + + auto f2 = strnstr(f1 + 1, " ", p - f1 + 1);//std::search(f1 + 1, p, sep.c_str(), sep.c_str() + sep.size()); + if (f2 == p || f1 >= f2) + { + throw TC_HttpRequest_Exception("[TC_HttpRequest::parseRequestHeader] http request format error: " + string(szBuffer, p - szBuffer)); + } + + //URL地址 + string sURL(f1 + 1, f2 - f1 - 1 ); + + //HTTP协议版本 + _version.assign(f2 + 1, p - f2 - 1); + + parseHeaderString(szBuffer, header, _headers); + + if (TC_Port::strncasecmp(f1 + 1, "https://", 8) != 0 ) + { + if (TC_Port::strncasecmp(f1 + 1, "http://", 7) != 0 ) + { + sURL = "http://" + getHost() + sURL; + } + } + + parseURL(sURL); +} + +void TC_HttpRequest::getHostPort(string &sDomain, uint32_t &iPort) +{ + sDomain = _httpURL.getDomain(); + + iPort = TC_Common::strto(_httpURL.getPort()); +} + +const string &TC_HttpRequest::getMethod() const +{ + auto it = TC_Http::HEADER_REVERSE.find(_requestType); + if(it != TC_Http::HEADER_REVERSE.end()) + { + return it->second; + } + else + { + throw TC_HttpRequest_Exception("[TC_HttpRequest::setMethod] http request command error: " + TC_Common::tostr(_requestType)); + } +} + +void TC_HttpRequest::setMethod(const char * sMethod) +{ + auto it = TC_Http::HEADER.find(sMethod); + if(it != TC_Http::HEADER.end()) + { + _requestType = it->second; + } + else + { + throw TC_HttpRequest_Exception("[TC_HttpRequest::setMethod] http request command error: " + string(sMethod)); + } +} + +void TC_HttpRequest::setPath(const char *path) +{ + _httpURL._sPath = path; +} + +void TC_HttpRequest::setDomain(const char * sDomain) +{ + _httpURL._sDomain = sDomain; +} + +void TC_HttpRequest::setScheme(const char * sScheme) +{ + _httpURL._sScheme = sScheme; +} + +int TC_HttpRequest::doRequest(TC_TCPClient& tcpClient, TC_HttpResponse& stHttpRsp) +{ + //只支持短连接模式 + setConnection("close"); + + string sSendBuffer = encode(); + + int iRet = tcpClient.send(sSendBuffer.c_str(), sSendBuffer.length()); + if (iRet != TC_ClientSocket::EM_SUCCESS) + { + return iRet; + } + + stHttpRsp.reset(); + + TC_NetWorkBuffer recvBuffer(NULL); + + while (true) + { + char buffer[8*1024]; + size_t iRecvLen = sizeof(buffer); + + iRet = tcpClient.recv(buffer, iRecvLen); + + if (iRet == TC_ClientSocket::EM_SUCCESS) + { + recvBuffer.addBuffer(buffer, iRecvLen); + } + + switch (iRet) + { + case TC_ClientSocket::EM_SUCCESS: + if (stHttpRsp.incrementDecode(recvBuffer)) + { + return TC_ClientSocket::EM_SUCCESS; + } + continue; + case TC_ClientSocket::EM_CLOSE: + stHttpRsp.incrementDecode(recvBuffer); + return TC_ClientSocket::EM_SUCCESS; + default: + return iRet; + } + } + + assert(true); + + return 0; + +} + +int TC_HttpRequest::doRequest(TC_HttpResponse &stHttpRsp, int iTimeout) +{ + //只支持短连接模式 + setConnection("close"); + + string sSendBuffer = encode(); + + string sHost; + uint32_t iPort; + + getHostPort(sHost, iPort); + + TC_TCPClient tcpClient; + tcpClient.init(sHost, iPort, iTimeout); + + int iRet = tcpClient.send(sSendBuffer.c_str(), sSendBuffer.length()); + if (iRet != TC_ClientSocket::EM_SUCCESS) + { + return iRet; + } + + stHttpRsp.reset(); + + TC_NetWorkBuffer recvBuffer(NULL); + + while (true) + { + char buffer[8*1024]; + size_t iRecvLen = sizeof(buffer); + + iRet = tcpClient.recv(buffer, iRecvLen); + + if (iRet == TC_ClientSocket::EM_SUCCESS) + { + recvBuffer.addBuffer(buffer, iRecvLen); + } + + switch (iRet) + { + case TC_ClientSocket::EM_SUCCESS: + if (stHttpRsp.incrementDecode(recvBuffer)) + { + return TC_ClientSocket::EM_SUCCESS; + } + continue; + case TC_ClientSocket::EM_CLOSE: + stHttpRsp.incrementDecode(recvBuffer); + return TC_ClientSocket::EM_SUCCESS; + default: + return iRet; + } + } + + assert(true); + + return 0; +} + +} + + diff --git a/util/src/tc_http2.cpp b/util/src/tc_http2.cpp index ce21f2cedf5a7952b201b2455da59c226e3cf8a6..99d88843b6643aafbb3c5a40f23eb4f3ea6f0be9 100644 --- a/util/src/tc_http2.cpp +++ b/util/src/tc_http2.cpp @@ -332,7 +332,8 @@ int TC_Http2Server::encodeResponse(const shared_ptrsecond.size(); } - DataPack dataPack(context->response.getContent().c_str(), context->response.getContent().size()); + const string &data = context->response.getContent(); + DataPack dataPack(data.c_str(), data.size()); nghttp2_data_provider data_prd; data_prd.source.ptr = (void*)&dataPack; @@ -497,23 +498,34 @@ TC_Http2Client::~TC_Http2Client() { } -int TC_Http2Client::submit(const string &method, const string &path, const map &header, const vector &buff) +int TC_Http2Client::submit(const TC_HttpRequest &request) { std::vector nva; const std::string smethod(":method"); - nghttp2_nv nv1 = MAKE_STRING_NV(smethod, method); - if (!method.empty()) { - nva.push_back(nv1); - } + nghttp2_nv nv1 = MAKE_STRING_NV(smethod, request.getMethod()); + nva.push_back(nv1); const std::string spath(":path"); - nghttp2_nv nv2 = MAKE_STRING_NV(spath, path); - if (!path.empty()) - nva.push_back(nv2); + nghttp2_nv nv2 = MAKE_STRING_NV(spath, request.getRequest()); + nva.push_back(nv2); + + const std::string sauthority(":authority"); + nghttp2_nv nv3 = MAKE_STRING_NV(sauthority, request.getURL().getDomain()); + nva.push_back(nv3); + + const std::string sscheme(":scheme"); + nghttp2_nv nv4 = MAKE_STRING_NV(sscheme, request.getURL().getScheme()); + nva.push_back(nv4); + +// cout << "submit:" << request.getMethod() << ", " << request.getRequest() << ", " << request.getURL().getDomain() << ", " << request.getURL().getScheme() << endl; - for (std::map::const_iterator it(header.begin()); it != header.end(); ++ it) + const TC_Http::http_header_type &header = request.getHeaders(); + for (auto it = header.begin(); it != header.end(); ++ it) { + if(TC_Port::strcasecmp(it->first.c_str(), "Content-Length") == 0 || it->second.empty()) + continue; + nghttp2_nv nv = MAKE_STRING_NV(it->first, it->second); nva.push_back(nv); } @@ -521,9 +533,9 @@ int TC_Http2Client::submit(const string &method, const string &path, const map> &out) diff --git a/util/src/tc_http_async.cpp b/util/src/tc_http_async.cpp index 0d138747920c9bae128b598af3ed2cf1b277f523..5d4f44092988b5035e3c94430cfb1bd78a33a631 100644 --- a/util/src/tc_http_async.cpp +++ b/util/src/tc_http_async.cpp @@ -22,26 +22,56 @@ namespace tars { TC_HttpAsync::AsyncRequest::AsyncRequest(TC_HttpRequest &stHttpRequest, TC_HttpAsync::RequestCallbackPtr &callbackPtr, bool bUseProxy) - : _pHttpAsync(NULL), _iUniqId(0), _callbackPtr(callbackPtr), _bUseProxy(bUseProxy), _isConnected(false) +: _pHttpAsync(NULL) +, _iUniqId(0) +, _sendBuffer(this) +, _recvBuffer(this) +, _callbackPtr(callbackPtr) +, _bUseProxy(bUseProxy) +, _isConnected(false) { memset(&_bindAddr, 0, sizeof(struct sockaddr)); _bindAddrSet = false; - _sReq = stHttpRequest.encode(); + vector buff; + stHttpRequest.encode(buff); + + _sendBuffer.addBuffer(std::move(buff)); stHttpRequest.getHostPort(_sHost, _iPort); +} + +TC_HttpAsync::AsyncRequest::AsyncRequest(TC_HttpRequest &stHttpRequest, RequestCallbackPtr &callbackPtr, const string &addr) +: _pHttpAsync(NULL) +, _iUniqId(0) +, _sendBuffer(this) +, _recvBuffer(this) +, _callbackPtr(callbackPtr) +, _bUseProxy(false) +, _isConnected(false) +{ + memset(&_bindAddr, 0, sizeof(struct sockaddr)); + + _bindAddrSet = false; - // _notify.createSocket(); + stHttpRequest.encode(_sendBuffer); + + vector v = TC_Common::sepstr(addr, ":"); + + if (v.size() < 2) + { + stHttpRequest.getHostPort(_sHost, _iPort); + } + else + { + _sHost = v[0]; + _iPort = TC_Common::strto(v[1]); + } } TC_HttpAsync::AsyncRequest::~AsyncRequest() { doClose(); - - // if (_pHttpAsync) - // _pHttpAsync->delConnection(_notify.getfd()); - - // _notify.close(); } void TC_HttpAsync::AsyncRequest::doClose() @@ -154,41 +184,16 @@ void TC_HttpAsync::AsyncRequest::timeout() } -string TC_HttpAsync::AsyncRequest::getError(const char* sDefault) const +string TC_HttpAsync::AsyncRequest::getError(const string &sDefault) const { int ret = TC_Exception::getSystemCode(); if(ret!= 0) { - return TC_Exception::parseError(ret); + return sDefault + ", ret:" + TC_Common::tostr(ret) + ", msg:" + TC_Exception::parseError(ret); } - return sDefault; + return sDefault + ", ret:" + TC_Common::tostr(ret); } -// string TC_HttpAsync::AsyncRequest::getError(const string &sDefault) const -// { -// string err; - -// if (_fd.isValid()) -// { -// int error; -// SOCKET_LEN_TYPE len = sizeof(error); -// _fd.getSockOpt(SO_ERROR, (void*)&error, len, SOL_SOCKET); -// if (error != 0) -// { -// err = strerror(error); -// } -// } - -// if (err.empty() && errno != 0) -// { -// err = strerror(errno); -// } - -// if (err.empty()) -// err = sDefault; - -// return err; -// } void TC_HttpAsync::AsyncRequest::doException(RequestCallback::FAILED_CODE ret, const string &e) { @@ -210,14 +215,15 @@ void TC_HttpAsync::AsyncRequest::doRequest() { ret = -1; - if (!_sReq.empty()) + if (!_sendBuffer.empty()) { - if ((ret = this->send(_sReq.c_str(), _sReq.length(), 0)) > 0) + auto data = _sendBuffer.getBufferPointer(); + if ((ret = this->send(data.first, data.second, 0)) > 0) { - _sReq = _sReq.substr(ret); + _sendBuffer.moveHeader(ret); } } - } while (ret > 0); + } while (ret > 0 && !_sendBuffer.empty()); //网络异常 if (ret == -2) @@ -239,27 +245,27 @@ void TC_HttpAsync::AsyncRequest::doReceive() { if ((recv = this->recv(buff, sizeof(buff), 0)) > 0) { - _sRsp.append(buff, recv); + _recvBuffer.addBuffer(buff, recv); } } while (recv > 0); if (recv == -2) { - doException(RequestCallback::Failed_Net, getError("recv error.")); + doException(RequestCallback::Failed_Net, getError("recv error")); } else { //增量decode - bool ret = _stHttpResp.incrementDecode(_sRsp); + bool ret = _stHttpResp.incrementDecode(_recvBuffer); - //有头部数据了 + //有头部数据了 if (_callbackPtr && !_stHttpResp.getHeaders().empty()) { bool bContinue = _callbackPtr->onContinue(_stHttpResp); if (!bContinue) { - doException(RequestCallback::Failed_Interrupt, getError("receive interrupt.")); + doException(RequestCallback::Failed_Interrupt, getError("receive interrupt")); return; } } @@ -282,8 +288,6 @@ void TC_HttpAsync::AsyncRequest::doReceive() doClose(); try { if (_callbackPtr) _callbackPtr->onSucc(_stHttpResp); } catch (...) { } - - // doException(RequestCallback::Failed_Close, getError("close by server.")); } } } @@ -291,15 +295,19 @@ void TC_HttpAsync::AsyncRequest::doReceive() void TC_HttpAsync::AsyncRequest::processNet(const epoll_event &ev) { - if (TC_Epoller::readEvent(ev))//events & EPOLLIN) + if (TC_Epoller::errorEvent(ev)) + { + doException(RequestCallback::Failed_Net, getError("net error")); + return; + } + + if (TC_Epoller::readEvent(ev)) { - // cout << "readEvent" << endl; doReceive(); } if (TC_Epoller::writeEvent(ev)) { - // cout << "writeEvent" << endl; doRequest(); } } @@ -309,12 +317,10 @@ void TC_HttpAsync::AsyncRequest::processNotify() //没有建立连接, 发起连接 if (!isValid()) { - // cout << "doConnect" << endl; doConnect(); } else { - // cout << "doRequest" << endl; doRequest(); } } @@ -331,15 +337,12 @@ TC_HttpAsync::TC_HttpAsync() : _terminate(false) _data = new http_queue_type(10000); - _epoller.create(1024); + _epoller.create(20480); - // _notify.createSocket(); _notify.init(&_epoller); uint64_t data = H64(_notify.notifyFd()) | 0; _notify.add(data); - - // _epoller.add(_notify.getfd(), data, EPOLLIN); } TC_HttpAsync::~TC_HttpAsync() @@ -348,7 +351,6 @@ TC_HttpAsync::~TC_HttpAsync() delete _data; - // _notify.close(); _notify.release(); _epoller.close(); @@ -359,9 +361,6 @@ void TC_HttpAsync::start() _tpool.init(1); _tpool.start(); - // TC_Functor cmd(this, &TC_HttpAsync::run); - // TC_Functor::wrapper_type wt(cmd); - _tpool.exec(std::bind(&TC_HttpAsync::run, this)); } @@ -435,7 +434,30 @@ void TC_HttpAsync::doAsyncRequest(TC_HttpRequest &stHttpRequest, RequestCallback _events.push_back(H64(_notify.notifyFd()) | uniqId); } _notify.notify(); - // addConnection(req->getNotifyfd(), uniqId, EPOLLIN); +} + +void TC_HttpAsync::doAsyncRequest(TC_HttpRequest &stHttpRequest, RequestCallbackPtr &callbackPtr, const string &addr) +{ + AsyncRequest * req = new AsyncRequest(stHttpRequest, callbackPtr, addr); + + if (_bindAddrSet) + { + req->setBindAddr(&_bindAddr); + } + + uint32_t uniqId = _data->generateId(); + + req->setUniqId(uniqId); + + req->setHttpAsync(this); + + _data->push(req, uniqId); + + { + std::lock_guard lock(_mutex); + _events.push_back(H64(_notify.notifyFd()) | uniqId); + } + _notify.notify(); } void TC_HttpAsync::addConnection(int fd, uint32_t uniqId, uint32_t events) @@ -541,7 +563,6 @@ void TC_HttpAsync::run() if ((int)fd == _notify.notifyFd()) { - // cout << "notify" << endl; deque events; { @@ -554,7 +575,6 @@ void TC_HttpAsync::run() { uint32_t uniqId = (uint32_t)data; - // cout << "socket uniqId:" << uniqId << endl; AsyncRequestPtr ptr = _data->getAndRefresh(uniqId); if (!ptr) continue; @@ -568,13 +588,10 @@ void TC_HttpAsync::run() uint32_t uniqId = TC_Epoller::getU32(ev, false); - // cout << "http socket uniqId:" << uniqId << endl; - AsyncRequestPtr ptr = _data->getAndRefresh(uniqId); if (!ptr) continue; - // assert(fd == ptr->getfd()); ptr->processNet(ev); } } diff --git a/util/src/tc_json.cpp b/util/src/tc_json.cpp old mode 100644 new mode 100755 index 5509ef147b473831aff5af4c79560e780675c105..c62d1c212ef4cc339175495b398cd51f6a093235 --- a/util/src/tc_json.cpp +++ b/util/src/tc_json.cpp @@ -333,6 +333,7 @@ JsonValueNumPtr TC_Json::getNum(BufferJsonReader & reader,char head) dResult=0-dResult; JsonValueNumPtr p = new JsonValueNum(); p->value=dResult; + p->isInt=!bFloat; return p; } @@ -449,11 +450,18 @@ string TC_Json::writeValue(const JsonValuePtr & p) return ostr; } +void TC_Json::writeValue(const JsonValuePtr& p, vector& buf) +{ + string ostr; + writeValue(p, ostr); + buf.assign(ostr.begin(), ostr.end()); +} + void TC_Json::writeValue(const JsonValuePtr & p, string& ostr) { if(!p) { - ostr = "null"; + ostr += "null"; return; } switch(p->getType()) @@ -600,6 +608,13 @@ JsonValuePtr TC_Json::getValue(const string & str) return getValue(reader); } +JsonValuePtr TC_Json::getValue(const vector& buf) +{ + BufferJsonReader reader; + reader.setBuffer(buf); + return getValue(reader); +} + //json里面定义的空白字符 bool TC_Json::isspace(char c) { diff --git a/util/src/tc_logger.cpp b/util/src/tc_logger.cpp index 98043e6cde11c74b285e4b7f3cb70e649106a241..969de60aaa5c0c1cfd3940c1efb0f8dd12ad6450 100644 --- a/util/src/tc_logger.cpp +++ b/util/src/tc_logger.cpp @@ -25,9 +25,10 @@ bool TC_LoggerRoll::_bDyeingFlag = false; //TC_ThreadMutex TC_LoggerRoll::_mutexDyeing; TC_SpinLock TC_LoggerRoll::_mutexDyeing; unordered_map TC_LoggerRoll::_mapThreadID; -const string TarsLogByDay::FORMAT = "%Y%m%d"; -const string TarsLogByHour::FORMAT = "%Y%m%d%H"; -const string TarsLogByMinute::FORMAT = "%Y%m%d%H%M"; + +const string LogByDay::FORMAT = "%Y%m%d"; +const string LogByHour::FORMAT = "%Y%m%d%H"; +const string LogByMinute::FORMAT = "%Y%m%d%H%M"; void TC_LoggerRoll::setupThread(TC_LoggerThreadGroup *pThreadGroup) { diff --git a/util/src/tc_md5.cpp b/util/src/tc_md5.cpp index 4fd6da64d5b61b43668215c314b061dcea268833..7aa55e159316779759435d2e5f40b2ed3ba23065 100644 --- a/util/src/tc_md5.cpp +++ b/util/src/tc_md5.cpp @@ -159,7 +159,7 @@ string TC_MD5::md5file(const string& fileFullName) MD5_CTX context; if(( f = fopen( fileFullName.c_str(), "rb" )) == NULL ) { - TARS_THROW_EXCEPTION_SYSCODE(TC_MD5_Exception, "[TC_MD5::md5file] fopen '" + fileFullName + "', error"); + THROW_EXCEPTION_SYSCODE(TC_MD5_Exception, "[TC_MD5::md5file] fopen '" + fileFullName + "', error"); } md5init(&context); diff --git a/util/src/tc_mmap.cpp b/util/src/tc_mmap.cpp index 8a75eb5909c3b72e9d195c33c4f001b4d5efeb00..689d77bc9cf70f06cda7b9c3a5abc612a2b706f5 100644 --- a/util/src/tc_mmap.cpp +++ b/util/src/tc_mmap.cpp @@ -70,7 +70,7 @@ void TC_Mmap::mmap(const char *file, size_t length) _hFile = CreateFile(file, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ| FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN|FILE_FLAG_WRITE_THROUGH|FILE_FLAG_NO_BUFFERING, NULL); if(_hFile == INVALID_HANDLE_VALUE) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Mmap_Exception, "[TC_Mmap::mmap] fopen file '" + string(file) + "' error"); + THROW_EXCEPTION_SYSCODE(TC_Mmap_Exception, "[TC_Mmap::mmap] fopen file '" + string(file) + "' error"); } _hMap = CreateFileMapping(_hFile, NULL, PAGE_READWRITE, 0, length, NULL); @@ -84,7 +84,7 @@ void TC_Mmap::mmap(const char *file, size_t length) } else { - TARS_THROW_EXCEPTION_SYSCODE(TC_Mmap_Exception, "[TC_Mmap::mmap] fopen file '" + string(file) + "' error"); + THROW_EXCEPTION_SYSCODE(TC_Mmap_Exception, "[TC_Mmap::mmap] fopen file '" + string(file) + "' error"); } _pAddr = (char*)MapViewOfFile(_hMap, FILE_MAP_ALL_ACCESS, 0, 0, length); @@ -94,7 +94,7 @@ void TC_Mmap::mmap(const char *file, size_t length) { CloseHandle(_hFile); CloseHandle(_hMap); - TARS_THROW_EXCEPTION_SYSCODE(TC_Mmap_Exception, "[TC_Mmap::mmap] fopen file '" + string(file) + "' error"); + THROW_EXCEPTION_SYSCODE(TC_Mmap_Exception, "[TC_Mmap::mmap] fopen file '" + string(file) + "' error"); } #else //注意_bCreate的赋值位置:保证多线程用一个对象的时候也不会有问题 @@ -103,14 +103,14 @@ void TC_Mmap::mmap(const char *file, size_t length) { if(errno != EEXIST) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Mmap_Exception, "[TC_Mmap::mmap] fopen file '" + string(file) + "' error"); + THROW_EXCEPTION_SYSCODE(TC_Mmap_Exception, "[TC_Mmap::mmap] fopen file '" + string(file) + "' error"); } else { fd = open(file, O_CREAT|O_RDWR, 0666); if(fd == -1) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Mmap_Exception, "[TC_Mmap::mmap] fopen file '" + string(file) + "' error"); + THROW_EXCEPTION_SYSCODE(TC_Mmap_Exception, "[TC_Mmap::mmap] fopen file '" + string(file) + "' error"); } _bCreate = false; } @@ -132,7 +132,7 @@ void TC_Mmap::mmap(const char *file, size_t length) { _pAddr = NULL; close(fd); - TARS_THROW_EXCEPTION_SYSCODE(TC_Mmap_Exception, "[TC_Mmap::mmap] mmap file '" + string(file) + "' error"); + THROW_EXCEPTION_SYSCODE(TC_Mmap_Exception, "[TC_Mmap::mmap] mmap file '" + string(file) + "' error"); } if(fd != -1) { @@ -159,7 +159,7 @@ void TC_Mmap::munmap() BOOL ret = FlushViewOfFile(_pAddr, 0); if(!ret) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Mmap_Exception, "[TC_Mmap::munmap] munmap error"); + THROW_EXCEPTION_SYSCODE(TC_Mmap_Exception, "[TC_Mmap::munmap] munmap error"); } UnmapViewOfFile(_pAddr); @@ -172,7 +172,7 @@ void TC_Mmap::munmap() int ret = ::munmap(_pAddr, _iLength); if(ret == -1) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Mmap_Exception, "[TC_Mmap::munmap] munmap error"); + THROW_EXCEPTION_SYSCODE(TC_Mmap_Exception, "[TC_Mmap::munmap] munmap error"); } #endif _pAddr = NULL; @@ -197,7 +197,7 @@ void TC_Mmap::msync(bool bSync) #endif if(ret != 0) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Mmap_Exception, "[TC_Mmap::msync] msync error"); + THROW_EXCEPTION_SYSCODE(TC_Mmap_Exception, "[TC_Mmap::msync] msync error"); } } diff --git a/util/src/tc_mysql.cpp b/util/src/tc_mysql.cpp index cbb79e3d344075da35226117b90aaf867d3f0d4d..ba42b26ffefff11246f40b5fb4690cf9e13b583a 100644 --- a/util/src/tc_mysql.cpp +++ b/util/src/tc_mysql.cpp @@ -238,7 +238,7 @@ string TC_Mysql::buildBatchSQLNoSafe(const string &sTableName, const string &com } ostringstream os; - os << command << " into `" << sTableName << "` (" << sColumnNames.str() << ") values " << sColumnValues.str(); + os << command << " into " << sTableName << " (" << sColumnNames.str() << ") values " << sColumnValues.str(); return os.str(); } @@ -341,7 +341,7 @@ string TC_Mysql::buildSQL(const string &sTableName, const string &command, const } } ostringstream os; - os << command << " into `" << sTableName << "` (" << sColumnNames.str() << ") values (" << sColumnValues.str() << ")"; + os << command << " into " << sTableName << " (" << sColumnNames.str() << ") values (" << sColumnValues.str() << ")"; return os.str(); } string TC_Mysql::buildBatchSQL(const string &sTableName, const string &command, const map >> &mpColumns) @@ -389,7 +389,7 @@ string TC_Mysql::buildBatchSQL(const string &sTableName, const string &command, sColumnValues << ","; } ostringstream os; - os << command << " into `" << sTableName << "` (" << sColumnNames.str() << ") values " << sColumnValues.str(); + os << command << " into " << sTableName << " (" << sColumnNames.str() << ") values " << sColumnValues.str(); return os.str(); } string TC_Mysql::buildUpdateSQL(const string &sTableName,const RECORD_DATA &mpColumns, const string &sWhereFilter) @@ -416,7 +416,7 @@ string TC_Mysql::buildUpdateSQL(const string &sTableName,const RECORD_DATA &mpCo } } ostringstream os; - os << "update `" << sTableName << "` set " << sColumnNameValueSet.str() << " " << sWhereFilter; + os << "update " << sTableName << " set " << sColumnNameValueSet.str() << " " << sWhereFilter; return os.str(); } diff --git a/util/src/tc_network_buffer.cpp b/util/src/tc_network_buffer.cpp index 6b9006a3706bf5f6922ddb644d6a0a431cbaf456..04df716c77c49cc628226dc758a0ecfc060622ff 100755 --- a/util/src/tc_network_buffer.cpp +++ b/util/src/tc_network_buffer.cpp @@ -12,20 +12,50 @@ namespace tars void TC_NetWorkBuffer::addBuffer(const shared_ptr & buff) { + if(buff->empty()) return; + _bufferList.push_back(buff); _length += buff->length(); } void TC_NetWorkBuffer::addBuffer(const vector& buff) { + if(buff.empty()) return; + _bufferList.push_back(std::make_shared(buff)); _length += buff.size(); } +void TC_NetWorkBuffer::addBuffer(const std::string& buff) +{ + if(buff.empty()) return; + + _bufferList.push_back(std::make_shared(buff.c_str(), buff.size())); + + _length += buff.size(); +} + void TC_NetWorkBuffer::addBuffer(const char* buff, size_t length) { - addBuffer(vector(buff, buff + length)); + if(buff == NULL || length == 0) return; + + addBuffer(vector(buff, buff + length)); +} + +TC_NetWorkBuffer::buffer_iterator TC_NetWorkBuffer::begin() const +{ + return buffer_iterator(this, 0); +} + +TC_NetWorkBuffer::buffer_iterator TC_NetWorkBuffer::end() const +{ + return buffer_iterator(this, this->getBufferLength()); +} + +TC_NetWorkBuffer::buffer_iterator TC_NetWorkBuffer::find(const char *str, size_t length) +{ + return std::search(begin(), end(), str, str + length); } void TC_NetWorkBuffer::clearBuffers() @@ -230,18 +260,9 @@ TC_NetWorkBuffer::PACKET_TYPE TC_NetWorkBuffer::checkHttp() { try { - mergeBuffers(); - - pair buffer = getBufferPointer(); - - if(buffer.first == NULL || buffer.second == 0) - { - return PACKET_LESS; - } - - bool b = TC_HttpRequest::checkRequest(buffer.first, buffer.second); + bool b = TC_HttpRequest::checkRequest(*this); - return b ? PACKET_FULL : PACKET_LESS; + return b ? PACKET_FULL : PACKET_LESS; } catch (exception &ex) { diff --git a/util/src/tc_openssl.cpp b/util/src/tc_openssl.cpp index 0818589d88717cf9bbdcbb6de44210dd94142ea0..a4cd69f99d905825c4e822d3518dcc5926186a0c 100644 --- a/util/src/tc_openssl.cpp +++ b/util/src/tc_openssl.cpp @@ -256,7 +256,7 @@ void TC_OpenSSL::initialize() } } -shared_ptr TC_OpenSSL::newCtx(const std::string& cafile, const std::string& certfile, const std::string& keyfile, bool verifyClient) +shared_ptr TC_OpenSSL::newCtx(const std::string& cafile, const std::string& certfile, const std::string& keyfile, bool verifyClient, const string &ciphers) { initialize(); @@ -270,10 +270,13 @@ shared_ptr TC_OpenSSL::newCtx(const std::string& cafile, const return NULL;\ } + int mode = SSL_VERIFY_NONE; if (verifyClient) - SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); - else - SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); + mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + if (!cafile.empty()) + mode |= SSL_VERIFY_PEER; + + SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); SSL_CTX_clear_options(ctx, SSL_OP_LEGACY_SERVER_CONNECT); @@ -293,11 +296,15 @@ shared_ptr TC_OpenSSL::newCtx(const std::string& cafile, const RETURN_IF_FAIL (SSL_CTX_check_private_key(ctx)); } + if(!ciphers.empty()) { + RETURN_IF_FAIL (SSL_CTX_set_cipher_list(ctx, ciphers.c_str())); + } #undef RETURN_IF_FAIL return std::make_shared(ctx); } + shared_ptr TC_OpenSSL::newSSL(const std::shared_ptr &ctx) { initialize(); diff --git a/util/src/tc_port.cpp b/util/src/tc_port.cpp index bed30250787cf5951b99c1f8195573f335e8c98d..79506b12949e9104213c5cfafadfd0014edb2693 100755 --- a/util/src/tc_port.cpp +++ b/util/src/tc_port.cpp @@ -28,8 +28,31 @@ #include "util/tc_strptime.h" #endif +#include + +using namespace std; + namespace tars { + +int TC_Port::strcmp(const char *s1, const char *s2) +{ +#if TARGET_PLATFORM_WINDOWS + return ::strcmp(s1, s2); +#else + return ::strcmp(s1, s2); +#endif +} + +int TC_Port::strncmp(const char *s1, const char *s2, size_t n) +{ +#if TARGET_PLATFORM_WINDOWS + return ::strncmp(s1, s2, n); +#else + return ::strncmp(s1, s2, n); +#endif +} + int TC_Port::strcasecmp(const char *s1, const char *s2) { #if TARGET_PLATFORM_WINDOWS @@ -171,4 +194,44 @@ int64_t TC_Port::getpid() return pid; } -} \ No newline at end of file +string TC_Port::getEnv(const string &name) +{ + char* p = getenv(name.c_str()); + string str = p ? string(p) : ""; + + return str; +} + +void TC_Port::setEnv(const string &name, const string &value) +{ +#if TARGET_PLATFORM_WINDOWS + SetEnvironmentVariable(name.c_str(), value.c_str()); +#else + setenv(name.c_str(), value.c_str(), true); +#endif +} + +string TC_Port::exec(const char *cmd) +{ + string fileData; +#if TARGET_PLATFORM_WINDOWS + FILE* fp = _popen(cmd, "r"); +#else + FILE* fp = popen(cmd, "r"); +#endif + static size_t buf_len = 2 * 1024 * 1024; + char *buf = new char[buf_len]; + memset(buf, 0, buf_len); + fread(buf, sizeof(char), buf_len - 1, fp); +#if TARGET_PLATFORM_WINDOWS + _pclose(fp); +#else + pclose(fp); +#endif + fileData = string(buf); + delete []buf; + + return fileData; +} + +} diff --git a/util/src/tc_sem_mutex.cpp b/util/src/tc_sem_mutex.cpp index f542cceb22579014e555a6c0476dd924a809b8f5..855185a57eadb60a3c4b13c16cc86d6b9b43c9e0 100644 --- a/util/src/tc_sem_mutex.cpp +++ b/util/src/tc_sem_mutex.cpp @@ -64,7 +64,7 @@ void TC_SemMutex::init(key_t iKey) //将所有信号量的值设置为0 if ( semctl( iSemID, 0, SETALL, arg ) == -1 ) { - TARS_THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::init] semctl error"); + THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::init] semctl error"); // throw TC_SemMutex_Exception("[TC_SemMutex::init] semctl error", TC_Exception::getSystemCode()); } } @@ -73,14 +73,14 @@ void TC_SemMutex::init(key_t iKey) //信号量已经存在 if ( errno != EEXIST ) { - TARS_THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::init] sem has exist error"); + THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::init] sem has exist error"); // throw TC_SemMutex_Exception("[TC_SemMutex::init] sem has exist error", TC_Exception::getSystemCode()); } //连接信号量 if ( (iSemID = semget( iKey, 2, 0666 )) == -1 ) { - TARS_THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::init] connect sem error"); + THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::init] connect sem error"); // throw TC_SemMutex_Exception("[TC_SemMutex::init] connect sem error", TC_Exception::getSystemCode()); } } @@ -144,7 +144,7 @@ bool TC_SemMutex::tryrlock() const } else { - TARS_THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::tryrlock] semop error"); + THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::tryrlock] semop error"); // throw TC_SemMutex_Exception("[TC_SemMutex::tryrlock] semop error", TC_Exception::getSystemCode()); } } @@ -208,7 +208,7 @@ bool TC_SemMutex::trywlock() const } else { - TARS_THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::trywlock] semop error"); + THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::trywlock] semop error"); // throw TC_SemMutex_Exception("[TC_SemMutex::trywlock] semop error", TC_Exception::getSystemCode()); } } @@ -252,14 +252,14 @@ void TC_SemMutex::init(key_t iKey) _mutex = CreateMutex(NULL, FALSE, key.c_str()); if (_mutex == NULL) { - TARS_THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::init] CreateMutex error"); + THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::init] CreateMutex error"); } _readEvent = CreateEvent(NULL, TRUE, TRUE, rkey.c_str()); if (_readEvent == NULL) { CloseHandle(_mutex); _mutex = NULL; - TARS_THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::init] CreateEvent error"); + THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::init] CreateEvent error"); } _writeEvent = CreateEvent(NULL, TRUE, TRUE, wkey.c_str()); if (_writeEvent == NULL) @@ -268,7 +268,7 @@ void TC_SemMutex::init(key_t iKey) _mutex = NULL; CloseHandle(_readEvent); _readEvent = NULL; - TARS_THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::init] CreateEvent error"); + THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::init] CreateEvent error"); } _semKey = iKey; } @@ -282,7 +282,7 @@ void TC_SemMutex::addWriter() const ReleaseMutex(_mutex); break; default: - TARS_THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::addWriter] WaitForSingleObject error"); + THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::addWriter] WaitForSingleObject error"); } } void TC_SemMutex::removeWriter() const @@ -295,7 +295,7 @@ void TC_SemMutex::removeWriter() const ReleaseMutex(_mutex); break; default: - TARS_THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::removeWriter] WaitForSingleObject error"); + THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::removeWriter] WaitForSingleObject error"); } } void TC_SemMutex::rlock() const @@ -313,7 +313,7 @@ void TC_SemMutex::rlock() const assert(_writers == 0); break; default: - TARS_THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::rlock] WaitForSingleObject error"); + THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::rlock] WaitForSingleObject error"); } } void TC_SemMutex::unrlock( ) const @@ -335,7 +335,7 @@ bool TC_SemMutex::tryrlock() const case WAIT_TIMEOUT: continue; default: - TARS_THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::tryrlock] WaitForSingleObject error"); + THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::tryrlock] WaitForSingleObject error"); } } } @@ -359,7 +359,7 @@ void TC_SemMutex::wlock() const break; default: removeWriter(); - TARS_THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::wlock] WaitForSingleObject error"); + THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::wlock] WaitForSingleObject error"); } } void TC_SemMutex::unwlock() const @@ -401,7 +401,7 @@ void TC_SemMutex::unlockImp() const ReleaseMutex(_mutex); break; default: - TARS_THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::unlockImp] WaitForSingleObject error"); + THROW_EXCEPTION_SYSCODE(TC_SemMutex_Exception, "[TC_SemMutex::unlockImp] WaitForSingleObject error"); } } DWORD TC_SemMutex::tryReadLockOnce() const diff --git a/util/src/tc_shm.cpp b/util/src/tc_shm.cpp index a4d8b3f0a0a239ee52d6984ce53586733e8dbd1f..84b5d95a5bd457e2896f90a0ba85436590ea4715 100755 --- a/util/src/tc_shm.cpp +++ b/util/src/tc_shm.cpp @@ -67,7 +67,7 @@ void TC_Shm::init(size_t iShmSize, key_t iKey, bool bOwner) //有可能是已经存在同样的key_shm,则试图连接 if ((_shemID = shmget(iKey, iShmSize, 0666)) < 0) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Shm_Exception, "[TC_Shm::init()] shmget error"); + THROW_EXCEPTION_SYSCODE(TC_Shm_Exception, "[TC_Shm::init()] shmget error"); // throw TC_Shm_Exception("[TC_Shm::init()] shmget error", TC_Exception::getSystemCode()); } } @@ -79,7 +79,7 @@ void TC_Shm::init(size_t iShmSize, key_t iKey, bool bOwner) //try to access shm if ((_pshm = shmat(_shemID, NULL, 0)) == (char *) - 1) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Shm_Exception, "[TC_Shm::init()] shmat error"); + THROW_EXCEPTION_SYSCODE(TC_Shm_Exception, "[TC_Shm::init()] shmat error"); // throw TC_Shm_Exception("[TC_Shm::init()] shmat error", TC_Exception::getSystemCode()); } diff --git a/util/src/tc_socket.cpp b/util/src/tc_socket.cpp index 7578995b4265d15db5cf6204fcd7124e204d3813..3333ddd0a3da14e0327db10e4973f87d9fde543a 100755 --- a/util/src/tc_socket.cpp +++ b/util/src/tc_socket.cpp @@ -80,7 +80,7 @@ void TC_Socket::createSocket(int iSocketType, int iDomain) if(_sock < 0) { _sock = INVALID_SOCKET; - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::createSocket] create socket error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::createSocket] create socket error"); // throw TC_Socket_Exception("[TC_Socket::createSocket] create socket error! :" + string(strerror(errno))); } else @@ -151,7 +151,7 @@ void TC_Socket::connect(const char *sPathName) int ret = connectNoThrow(sPathName); if(ret < 0) { - TARS_THROW_EXCEPTION_SYSCODE(TC_SocketConnect_Exception, "[TC_Socket::connect] connect error"); + THROW_EXCEPTION_SYSCODE(TC_SocketConnect_Exception, "[TC_Socket::connect] connect error"); } } @@ -173,7 +173,7 @@ void TC_Socket::getPeerName(struct sockaddr *pstPeerAddr, SOCKET_LEN_TYPE &iPeer { if(getpeername(_sock, pstPeerAddr, &iPeerLen) < 0) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::getPeerName] getpeername error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::getPeerName] getpeername error"); } } @@ -199,7 +199,7 @@ void TC_Socket::getSockName(struct sockaddr *pstSockAddr, SOCKET_LEN_TYPE &iSock { if(getsockname(_sock, pstSockAddr, &iSockLen) < 0) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::getSockName] getsockname error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::getSockName] getsockname error"); } } @@ -209,7 +209,11 @@ SOCKET_TYPE TC_Socket::accept(TC_Socket &tcSock, struct sockaddr *pstSockAddr, S SOCKET_TYPE ifd; +#if TARGET_PLATFORM_WINDOWS + ifd = ::accept(_sock, pstSockAddr, &iSockLen); +#else while ((ifd = ::accept(_sock, pstSockAddr, &iSockLen)) < 0 && errno == EINTR); +#endif tcSock._sock = ifd; tcSock._iDomain = _iDomain; @@ -222,7 +226,7 @@ void TC_Socket::parseAddr(const string &sAddr, struct in_addr &stSinAddr) int iRet = inet_pton(AF_INET, sAddr.c_str(), &stSinAddr); if(iRet < 0) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::parseAddr] inet_pton(" + sAddr + ") error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::parseAddr] inet_pton(" + sAddr + ") error"); } #if TARGET_PLATFORM_LINUX else if (iRet == 0) @@ -236,7 +240,7 @@ void TC_Socket::parseAddr(const string &sAddr, struct in_addr &stSinAddr) if (pstHostent == NULL) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::parseAddr] gethostbyname_r(" + sAddr + ") error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::parseAddr] gethostbyname_r(" + sAddr + ") error"); // throw TC_Socket_Exception("[TC_Socket::parseAddr] gethostbyname_r(" + sAddr + ") error", TC_Exception::getSystemCode()); } @@ -256,7 +260,7 @@ void TC_Socket::parseAddr(const string &sAddr, struct in_addr &stSinAddr) int err = getaddrinfo(sAddr.c_str(), NULL, &hints, &ailist); if (err != 0) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::parseAddr] getaddrinfo(" + sAddr + ") error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::parseAddr] getaddrinfo(" + sAddr + ") error"); } else { @@ -278,7 +282,7 @@ void TC_Socket::parseAddr(const string &host, struct in6_addr &stSinAddr) int iRet = inet_pton(AF_INET6, host.c_str(), &stSinAddr); if(iRet < 0) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::parseAddr] inet_pton(" + host + ") error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::parseAddr] inet_pton(" + host + ") error"); } else if(iRet == 0) { @@ -381,7 +385,7 @@ void TC_Socket::bind(const struct sockaddr *pstBindAddr, SOCKET_LEN_TYPE iAddrLe if(::bind(_sock, pstBindAddr, iAddrLen) < 0) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::bind] bind error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::bind] bind error"); } } @@ -440,7 +444,7 @@ void TC_Socket::connect(const string &sServerAddr, uint16_t port) if(ret < 0) { - TARS_THROW_EXCEPTION_SYSCODE(TC_SocketConnect_Exception, "[TC_Socket::connect] connect error"); + THROW_EXCEPTION_SYSCODE(TC_SocketConnect_Exception, "[TC_Socket::connect] connect error"); } } @@ -454,7 +458,7 @@ void TC_Socket::listen(int iConnBackLog) { if (::listen(_sock, iConnBackLog) < 0) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::listen] listen error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::listen] listen error"); } } @@ -543,7 +547,7 @@ void TC_Socket::shutdown(int iHow) { if (::shutdown(_sock, iHow) < 0) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::shutdown] shutdown error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::shutdown] shutdown error"); } } @@ -572,7 +576,7 @@ void TC_Socket::setNoCloseWait() if(setSockOpt(SO_LINGER, (const void *)&stLinger, sizeof(linger), SOL_SOCKET) == -1) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setNoCloseWait] error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setNoCloseWait] error"); } } @@ -584,7 +588,7 @@ void TC_Socket::setCloseWait(int delay) if(setSockOpt(SO_LINGER, (const void *)&stLinger, sizeof(linger), SOL_SOCKET) == -1) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setCloseWait] error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setCloseWait] error"); // throw TC_Socket_Exception("[TC_Socket::setCloseWait] error", TC_Exception::getSystemCode()); } @@ -598,7 +602,7 @@ void TC_Socket::setCloseWaitDefault() if(setSockOpt(SO_LINGER, (const void *)&stLinger, sizeof(linger), SOL_SOCKET) == -1) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setCloseWait] error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setCloseWait] error"); } } @@ -608,7 +612,7 @@ void TC_Socket::setTcpNoDelay() if(setSockOpt(TCP_NODELAY, (char*)&flag, int(sizeof(int)), IPPROTO_TCP) == -1) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setTcpNoDelay] error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setTcpNoDelay] error"); } } @@ -617,7 +621,7 @@ void TC_Socket::setKeepAlive() int flag = 1; if(setSockOpt(SO_KEEPALIVE, (char*)&flag, int(sizeof(int)), SOL_SOCKET) == -1) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setKeepAlive] error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setKeepAlive] error"); } } @@ -625,7 +629,7 @@ void TC_Socket::setSendBufferSize(int sz) { if(setSockOpt(SO_SNDBUF, (char*)&sz, int(sizeof(int)), SOL_SOCKET) == -1) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setKeepsetSendBufferSizeAlive] error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setKeepsetSendBufferSizeAlive] error"); } } @@ -635,7 +639,7 @@ int TC_Socket::getSendBufferSize() const SOCKET_LEN_TYPE len = sizeof(sz); if (getSockOpt(SO_SNDBUF, (void*)&sz, len, SOL_SOCKET) == -1 || len != sizeof(sz)) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::getSendBufferSize] error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::getSendBufferSize] error"); } return sz; @@ -645,7 +649,7 @@ void TC_Socket::setRecvBufferSize(int sz) { if(setSockOpt(SO_RCVBUF, (char*)&sz, int(sizeof(int)), SOL_SOCKET) == -1) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setRecvBufferSize] error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setRecvBufferSize] error"); } } @@ -655,7 +659,7 @@ int TC_Socket::getRecvBufferSize() const SOCKET_LEN_TYPE len = sizeof(sz); if (getSockOpt(SO_RCVBUF, (void*)&sz, len, SOL_SOCKET) == -1 || len != sizeof(sz)) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::getRecvBufferSize] error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::getRecvBufferSize] error"); } return sz; @@ -668,7 +672,7 @@ void TC_Socket::ignoreSigPipe() { if (setSockOpt(SO_NOSIGPIPE, (char*)&set, int(sizeof(int)), SOL_SOCKET) == -1) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::ignoreSigPipe] error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::ignoreSigPipe] error"); } #endif } @@ -681,7 +685,7 @@ void TC_Socket::setblock(SOCKET_TYPE fd, bool bBlock) if ((val = fcntl(fd, F_GETFL, 0)) == -1) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setblock] fcntl [F_GETFL] error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setblock] fcntl [F_GETFL] error"); // throw TC_Socket_Exception("[TC_Socket::setblock] fcntl [F_GETFL] error", TC_Exception::getSystemCode()); } @@ -696,7 +700,7 @@ void TC_Socket::setblock(SOCKET_TYPE fd, bool bBlock) if (fcntl(fd, F_SETFL, val) == -1) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setblock] fcntl [F_SETFL] error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setblock] fcntl [F_SETFL] error"); } #else unsigned long ul = 1; @@ -705,7 +709,7 @@ void TC_Socket::setblock(SOCKET_TYPE fd, bool bBlock) ret = ioctlsocket(fd, FIONBIO, (unsigned long *)&ul); if (ret == SOCKET_ERROR) { - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setblock] ioctlsocket [FIONBIO] error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setblock] ioctlsocket [FIONBIO] error"); } #endif @@ -786,7 +790,7 @@ clean: // #if TARGET_PLATFORM_LINUX||TARGET_PLATFORM_IOS // #undef closesocket // #endif - TARS_THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::createPipe] error"); + THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::createPipe] error"); } #if TARGET_PLATFORM_LINUX diff --git a/util/src/tc_spin_lock.cpp b/util/src/tc_spin_lock.cpp index da17513bef8c02a59bda544ef7500082eadcedca..ad2bae4e24458f3ff2e004c33ad942dfbde2c8e5 100755 --- a/util/src/tc_spin_lock.cpp +++ b/util/src/tc_spin_lock.cpp @@ -35,9 +35,9 @@ bool TC_SpinLock::tryLock() const int trys = 100; for (; trys > 0 && _flag.test_and_set(std::memory_order_acquire); --trys) { -#if TARGET_PLATFORM_LINUX - asm volatile("rep; nop" ::: "memory"); -#endif +//#if TARGET_PLATFORM_LINUX +// asm volatile("rep; nop" ::: "memory"); +//#endif } diff --git a/util/src/tc_xml.cpp b/util/src/tc_xml.cpp new file mode 100755 index 0000000000000000000000000000000000000000..8218e3d2143e46694935307755f0cc3020ff6535 --- /dev/null +++ b/util/src/tc_xml.cpp @@ -0,0 +1,532 @@ +#include "util/tc_xml.h" +#include "util/tc_common.h" + +#include +#include +#include +#include + +namespace tars +{ + +#define FILTER_SPACE while(isspace((int)reader.get())) {reader.skip();} +#define FILTER_NODENAME while(lookup_node_name[(int)reader.get()]) {reader.skip();} +#define XML_PARSE_ERROR(what) { throw TC_Xml_Exception(what); } + +// Node name (anything but space \n \r \t / > ? \0) +const unsigned char lookup_node_name[256] = +{ + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F +}; + +//// Text (i.e. PCDATA) (anything but < \0) +//const unsigned char lookup_text[256] = +//{ +// // 0 1 2 3 4 5 6 7 8 9 A B C D E F +// 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 +// 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, // 2 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F +//}; + +// Text (i.e. PCDATA) that does not require processing when ws normalization is disabled +// (anything but < \0 &) +const unsigned char lookup_text_pure_no_ws[256] = +{ + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F +}; + + +// Digits (dec and hex, 255 denotes end of numeric character reference) +const unsigned char lookup_digits[256] = +{ + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 0 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 1 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 2 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,255,255,255,255,255,255, // 3 + 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 4 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 5 + 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 6 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 7 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 8 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 9 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // A + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // B + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // C + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // D + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // E + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 // F +}; + +XmlValuePtr TC_Xml::getValue(const string& str) +{ + BufferXmlReader reader; + XmlValueObjPtr p = new XmlValueObj(); + + // Parse BOM, if any + reader.setBuffer(str.c_str(), str.length()); + if ((unsigned char)reader.get(0) == 0xEF && + (unsigned char)reader.get(1) == 0xBB && + (unsigned char)reader.get(2) == 0xBF) + { + reader._pos += 3; // Skup utf-8 bom + } + + FILTER_SPACE; + // Parse and append new child + if (reader.get() == '<' && reader.get(1) == '?') + { + reader.skip(2); + ignoreDeclaration(reader); + } + + FILTER_SPACE; + return getNode(reader); +} + +XmlValuePtr TC_Xml::getValue(const vector& buf) +{ + BufferXmlReader reader; + XmlValueObjPtr p = new XmlValueObj(); + + // Parse BOM, if any + reader.setBuffer(buf); + if ((unsigned char)reader.get(0) == 0xEF && + (unsigned char)reader.get(1) == 0xBB && + (unsigned char)reader.get(2) == 0xBF) + { + reader._pos += 3; // Skup utf-8 bom + } + + FILTER_SPACE; + // Parse and append new child + if (reader.get() == '<' && reader.get(1) == '?') + { + reader.skip(2); + ignoreDeclaration(reader); + } + + FILTER_SPACE; + return getNode(reader); +} + +XmlValuePtr TC_Xml::getNode(BufferXmlReader& reader, const string& nodename) +{ + XmlValueObjPtr p = new XmlValueObj(); + while(1) + { + // 开始符号 + if (!reader.expect('<')) + { + return getValue(reader); + } + + // 判断是否是注释 + if (ignoreComment(reader)) + { + continue; + } + + // CDATA + if (reader.get(0) == '!' && reader.get(1) == '[' && reader.get(2) == 'C' && reader.get(3) == 'D' && + reader.get(4) == 'A' && reader.get(5) == 'T' && reader.get(6) == 'A' && reader.get(7) == '[') + { + reader.skip(8); + return getCdata(reader); + } + + // 判断是否是node结束符 + if (isEndNode(reader, nodename)) + { + break; + } + + // 取node名称 + FILTER_SPACE; + size_t pos = reader.pos(); + FILTER_NODENAME; + string name = string(reader._buf + pos, reader.pos() - pos); + while(reader.read() != '>'); + if (reader.get(-2) == '/') + { + XmlValuePtr s = new XmlValueString(); + insertArray(name, s, p); + FILTER_SPACE; + continue; + } + + // 取Node内容 + FILTER_SPACE; + XmlValuePtr q = getNode(reader, name); + insertArray(name, q, p); + + // 遇到尾部就退出 + FILTER_SPACE; + if (reader.hasEnd()) + { + break; + } + } + + if (p->value.size() == 0) // node内容为空直接返回空字符对象 + { + XmlValuePtr ss = new XmlValueString(); + return ss; + } + return p; +} + +bool TC_Xml::isEndNode(BufferXmlReader& reader, const string& nodename) +{ + if (reader.get() == '/' && reader.get(1) != '>' && !nodename.empty()) + { + size_t lastpos = reader.pos(); + size_t start = 0; + while (isspace(reader.get(start++))); + size_t end = start; + while(lookup_node_name[(int)reader.get(++end)]); + string backname = string(reader._buf + lastpos + start, end - start); + if (backname == nodename) + { + while(reader.read() != '>'); + return true; + } + } + return false; +} + +XmlValueStringPtr TC_Xml::getCdata(BufferXmlReader& reader) +{ + size_t pos = reader.pos(); + XmlValueStringPtr p = new XmlValueString(true); + while (reader.get() != ']' || reader.get(1) != ']' || reader.get(2) != '>') + { + reader.skip(1); + } + p->value = string(reader._buf + pos, reader.pos() - pos); + reader.skip(3); + while(reader.read() != '>'); + return p; +} + +XmlValueStringPtr TC_Xml::getValue(BufferXmlReader& reader) +{ + XmlValueStringPtr p = new XmlValueString(); + FILTER_SPACE + while (lookup_text_pure_no_ws[(int)reader.get()]) + { + if (reader.get() != '&') + { + p->value.append(1, reader.read()); + } + + if (reader.get(1) == 'g' && reader.get(2) == 't' && reader.get(3) == ';') + { + p->value.append(1, '>'); + reader.skip(4); + continue; + } + + if (reader.get(1) == 'l' && reader.get(2) == 't' && reader.get(3) == ';') + { + p->value.append(1, '<'); + reader.skip(4); + continue; + } + + if (reader.get(1) == 'a' && reader.get(2) == 'm' && reader.get(3) == 'p' && reader.get(4) == ';') + { + p->value.append(1, '&'); + reader.skip(5); + continue; + } + + if (reader.get(1) == 'a' && reader.get(2) == 'p' && reader.get(3) == 'o' && reader.get(4) == 's' && reader.get(5) == ';') + { + p->value.append(1, '\''); + reader.skip(6); + continue; + } + + if (reader.get(1) == 'q' && reader.get(2) == 'u' && reader.get(3) == 'o' && reader.get(4) == 's' && reader.get(5) == ';') + { + p->value.append(1, '"'); + reader.skip(6); + continue; + } + + // 中文转码 + if (reader.get(1) == '#') + { + unsigned long code = 0; + if (reader.get(2) == 'x') + { + reader.skip(3); + unsigned char digit = reader.get(); + while (lookup_digits[digit] != 0xFF) + { + code = code * 16 + digit; + digit = (unsigned char)reader.read(); + } + } + else + { + reader.skip(2); + unsigned char digit = reader.get(); + while (lookup_digits[digit] != 0xFF) + { + code = code * 10 + digit; + digit = (unsigned char)reader.read(); + } + } + + if (reader.read() != ';') + { + XML_PARSE_ERROR("expected ;"); + } + + // Insert UTF8 sequence + char text[8] = {0}; + if (code < 0x80) // 1 byte sequence + { + text[0] = static_cast(code); + } + else if (code < 0x800) // 2 byte sequence + { + text[1] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[0] = static_cast(code | 0xc0); + } + else if (code < 0x10000) // 3 byte sequence + { + text[2] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[1] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[0] = static_cast(code | 0xE0); + } + else if (code < 0x110000) // 4 byte sequence + { + text[3] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[2] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[1] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[0] = static_cast(code | 0xF0); + } + else // Invalid, only codes up to 0x10FFFF are allowed in Unicode + { + XML_PARSE_ERROR("invalid numeric character entity"); + } + p->value.append(text); + } + } + while(reader.read() != '>'); + return p; +} + +void TC_Xml::insertArray(const string& name, XmlValuePtr& v, XmlValueObjPtr& p) +{ + if (p->value.find(name) == p->value.end()) + { + p->value[name] = v; + } + else if (p->value[name]->getType() == v->getType()) + { + XmlValueArrayPtr array = new XmlValueArray(); + array->push_back(p->value[name]); + array->push_back(v); + p->value[name] = array; + } + else if (p->value[name]->getType() == eXmlTypeArray) + { + XmlValueArrayPtr array = XmlValueArrayPtr::dynamicCast(p->value[name]); + if (array->value.size() > 0 && array->value[0]->getType() == v->getType()) + { + array->push_back(v); + p->value[name] = array; + } + } +} + +bool TC_Xml::ignoreComment(BufferXmlReader& reader) +{ + if (reader.get() == '!' && reader.get(1) == '-' && reader.get(2) == '-') + { + reader.skip(3); + while (1) + { + if (reader.read() == '-' && reader.read() == '-' && reader.read() == '>') + { + return true; + } + } + } + return false; +} + +void TC_Xml::ignoreDeclaration(BufferXmlReader& reader) +{ + if ((reader.get(0) == 'x' || reader.get(0) == 'X') && + (reader.get(1) == 'm' || reader.get(1) == 'M') && + (reader.get(2) == 'l' || reader.get(2) == 'L') && + isspace(reader.get(3))) + { + // '') + { + return; + } + } + } + XML_PARSE_ERROR("unexpected xml head") +} + +string TC_Xml::writeValue(const XmlValuePtr & p, bool bHead) +{ + ostringstream os; + os << (bHead ? "" : ""); + if(!p || p->getType() != eXmlTypeObj) + { + return os.str(); + } + + writeObj(os, XmlValueObjPtr::dynamicCast(p)); + return os.str(); +} + +void TC_Xml::writeValue(const XmlValuePtr& p, vector& buf, bool bHead) +{ + if(!p || p->getType() != eXmlTypeObj) + { + return; + } + + ostringstream os; + os << (bHead ? "" : ""); + writeObj(os, XmlValueObjPtr::dynamicCast(p)); + string s = os.str(); + buf.assign(s.begin(), s.end()); +} + +void TC_Xml::writeObj(std::ostream& os, const XmlValuePtr& p) +{ + if (p->getType() != eXmlTypeObj) + { + XML_PARSE_ERROR("not support but xmlobj") + } + + os << "\n"; + XmlValueObjPtr q = XmlValueObjPtr::dynamicCast(p); + for (map::const_iterator it = q->value.begin(); it != q->value.end(); it++) + { + switch (it->second->getType()) + { + case eXmlTypeString: + os << "<" << it->first << ">"; + writeString(os, it->second); + os << "first << ">\n"; + break; + case eXmlTypeArray: + writeArray(os, it->first, it->second); + break; + case eXmlTypeObj: + default: + os << "<" << it->first << ">"; + writeObj(os, it->second); + os << "first << ">\n"; + } + } +} + +void TC_Xml::writeString(std::ostream& os, const XmlValuePtr& p) +{ + XmlValueStringPtr q = XmlValueStringPtr::dynamicCast(p); + if (q->cdata) + { + os << "value << "]]>"; + return; + } + writeEChar(os, q->value); +} + +void TC_Xml::writeArray(std::ostream& os, const string& name, const XmlValuePtr& p) +{ + XmlValueArrayPtr q = XmlValueArrayPtr::dynamicCast(p); + for (size_t i = 0; i < q->value.size(); i++) + { + os << "<" << name << ">"; + if (q->value[i]->getType() == eXmlTypeString) + { + writeString(os, q->value[i]); + } + else + { + writeObj(os, q->value[i]); + } + os << "\r\n"; + } +} + +void TC_Xml::writeEChar(std::ostream& os, const string& data) +{ + string s(data); + s = TC_Common::replace(s, "<", "<"); + s = TC_Common::replace(s, ">", "<"); + s = TC_Common::replace(s, "\'", "'"); + s = TC_Common::replace(s, "\"", """); + os << s; +} + +//Xml里面定义的空白字符 +bool TC_Xml::isspace(char c) +{ + if(c == ' ' || c == '\t' || c == '\r' || c == '\n') + return true; + return false; +} + +}