...
 
Commits (42)
    https://gitcode.net/oceanbase/oblogmsg/-/commit/875cd0c23f9065239f74eb0f1b56f34a3d150a02 add LICENSE file 2021-07-12T19:55:27+08:00 xiaoyi.yl xiaoyi.yl@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/0e12b7c9d812f371676d60f5833061c1d7fcb753 add .clang-format and git-hooks 2021-08-25T17:10:22+08:00 忠阳 fanzhongyang.fzy@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/47777a85d82c7771c734fc7bbd73593a80f7296a add submodule googletest 2021-08-25T17:10:35+08:00 忠阳 fanzhongyang.fzy@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/bf5d80edd711f86442c7da0ffce15fff01e65d90 impl oblogmsg 2021-08-25T17:13:00+08:00 忠阳 fanzhongyang.fzy@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/8f4438873932c9d9dade4b8f893a32c4acd1df17 add README 2021-08-25T17:16:27+08:00 忠阳 fanzhongyang.fzy@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/23e35e057145317dab3fed7be177cf89624f0fde fixed potential security issues 2021-09-02T16:45:07+08:00 忠阳 fanzhongyang.fzy@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/cb667b5d5551260fc08d647749d15bd1b79ac60f fix white box scan 2021-09-24T11:46:27+08:00 wangyunlai.wyl wangyunlai.wyl@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/fe358571205533d2a1246abfce806faf48e9e016 Merge branch 'hotfix/whitebox' into 'master' 2021-09-24T11:59:03+08:00 官明 wangzelin.wzl@antgroup.com fix white box scan See merge request !1409679 https://gitcode.net/oceanbase/oblogmsg/-/commit/47b0bccb5971e8f20da779d3a7695ebc42aff31e fix white scan 2021-09-24T13:42:34+08:00 wangyunlai.wyl wangyunlai.wyl@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/ac7fb2cd83991b30a4832af595300aa35f916be3 remove redundant memcpy 2021-09-24T14:04:07+08:00 wangyunlai.wyl wangyunlai.wyl@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/f0ddb524fc90797de5d60d0d9c000734ea57673a Merge branch 'hotfix/whitebox' into 'master' 2021-09-24T14:16:04+08:00 官明 wangzelin.wzl@antgroup.com fix white scan See merge request !1409827 https://gitcode.net/oceanbase/oblogmsg/-/commit/3461feed29043d885ec1a8eb9754349c26a42c89 change licence 2021-09-27T10:36:54+08:00 wangyunlai.wyl wangyunlai.wyl@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/de4dbfcdb0455db21707df1f6e1bbc5ba20c97a2 Merge branch 'doc/licence' into 'master' 2021-09-27T11:03:06+08:00 官明 wangzelin.wzl@antgroup.com change licence See merge request !1413267 https://gitcode.net/oceanbase/oblogmsg/-/commit/5f6fcc55db996953ac63c63ea2062f5f7f30db36 add cmake c++11 abi option which disabled by default 2021-09-29T18:06:55+08:00 yuqi.fy yuqi.fy@alibaba-inc.com https://gitcode.net/oceanbase/oblogmsg/-/commit/4745dec4330cb578dbc0a0502f439a3789db0dc4 using pragma once as headers include guard to avoid conflics with third-party 2021-09-29T18:55:46+08:00 yuqi.fy yuqi.fy@alibaba-inc.com https://gitcode.net/oceanbase/oblogmsg/-/commit/b89736e7d7b1a353868e9ec20904704b9c889f65 add make oblogmsg rpm 2021-10-11T01:22:31+08:00 忠阳 fanzhongyang.fzy@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/700782933cd962e1c1fe89c19e40979681ce7584 use cmake in modern way 2021-10-12T14:22:43+08:00 xiaoyi.yl xiaoyi.yl@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/156cfeabde6ecc6a7580716f048f26816df05863 Merge branch 'make-rpm' into 'master' 2021-10-12T14:57:19+08:00 萧壹 xiaoyi.yl@antfin.com install &amp; package oblogmsg See merge request !1423334 https://gitcode.net/oceanbase/oblogmsg/-/commit/f8c28188c9bae03a3a78b06d1944f5c79280248d install oblogmsgConfigVersion.cmake 2021-10-12T20:26:30+08:00 萧壹 xiaoyi.yl@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/ed1793666369bf9dfc8cd17788e62e52587b4382 formated README.md 2021-10-18T16:06:59+08:00 忠阳 fanzhongyang.fzy@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/b33096b9157f5020b45a90051f33bc97bda405e3 format README.md,add blank space 2021-10-18T16:40:30+08:00 忠阳 fanzhongyang.fzy@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/beafb2f8f9ba4c75b0a3a2ebcc7e322c84e12e61 add crc32 verification 2021-11-12T17:39:49+08:00 忠阳 fanzhongyang.fzy@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/fda54ffe4758db22cc0e0a4c4e02e9212edbd7b8 hidden symbols in LogMsgBuf.cpp,set HIDDEN_DMB_SYMBOLS = true to enable 2021-11-16T20:12:30+08:00 忠阳 fanzhongyang.fzy@antgroup.com it https://gitcode.net/oceanbase/oblogmsg/-/commit/0f25623c6ae77230136e9e3c888f24e16be3dde7 Merge branch 'crc32-rebase' into 'master' 2021-11-19T14:10:27+08:00 萧壹 xiaoyi.yl@antfin.com Crc32 rebase See merge request !1466148 https://gitcode.net/oceanbase/oblogmsg/-/commit/8e3b1d969298d41aab5d3ca7c534164736b24c4e change __thread lmb to LogMsgBuf class,set it in toString 2021-11-24T17:53:14+08:00 忠阳 fanzhongyang.fzy@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/fe014d10f66b5ead295b9c1440b3cf4ca47049c9 Merge branch 'dmb' into 'master' 2021-11-24T18:05:12+08:00 萧壹 xiaoyi.yl@antfin.com Dmb See merge request !1475512 https://gitcode.net/oceanbase/oblogmsg/-/commit/756c4e0ee164f355823d9dbeaca9b043c7f7698e update posInfo when Serialize 2022-07-06T17:33:11+08:00 忠阳 fanzhongyang.fzy@oceanbase.com https://gitcode.net/oceanbase/oblogmsg/-/commit/be5a61dd79cc82fa1f464392612620a35c9844b6 Merge branch 'hotfix-posInfo' into 'master' 2022-07-07T10:54:49+08:00 萧壹 xiaoyi.yl@antfin.com update posInfo when Serialize 向反序列化出来的 record 设置值,再序列化时不会更新设置的新值 See merge request !1719785 https://gitcode.net/oceanbase/oblogmsg/-/commit/66b38ea4a5ba6edf09fff3ad3aec71d0a12b5a22 support rpm build 2022-09-16T11:17:25+08:00 wenxingsen.wxs wenxingsen.wxs@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/9f8c753e6b1d46548f88a74834c031c36b82d5e5 fix deps name 2022-09-16T11:21:16+08:00 wenxingsen.wxs wenxingsen.wxs@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/c3cd76895836238125224cc680d859277eb64897 fix spec bad spell 2022-09-16T11:29:24+08:00 wenxingsen.wxs wenxingsen.wxs@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/2c9e271f5737e99bb0998069d4d6bab730f75d11 fix lost endInfo when serialize 2022-09-29T18:04:33+08:00 wangxiantong.wxt wangxiantong.wxt@antgroup.com 修复二次序列化丢失endInfo属性 Link: <a href="https://code.alibaba-inc.com/oceanbase-ce-publish/oblogmsg/codereview/10309006" rel="nofollow noreferrer noopener" target="_blank">https://code.alibaba-inc.com/oceanbase-ce-publish/oblogmsg/codereview/10309006</a> * fix lost endInfo when serialize * 1.fix replace exchangePosInfoToLe to exchangeEndInfoToLe 2.add recordUsec unit test * add unit test * add unit test https://gitcode.net/oceanbase/oblogmsg/-/commit/b2c217a4b2869d0d20ad2030d5a018f9327e517c add el8 deps 2022-10-04T19:59:28+08:00 wenxingsen.wxs wenxingsen.wxs@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/39626c3a26fb12aac0e085f6b39dd86c6f00ed35 add license head 2022-10-10T17:50:21+08:00 自凡 wangxiantong.wxt@alibaba-inc.com https://gitcode.net/oceanbase/oblogmsg/-/commit/cf5711032e0109334c451d565c77b26f52d1dbf0 add flag BUILD_AS_MAIN_PROJECT 2022-10-11T16:38:43+08:00 wenxingsen.wxs wenxingsen.wxs@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/e1f10fb4e6681911b4b59b75b1523ab8d21f9f8d fix bad speel 2022-10-11T16:41:52+08:00 wenxingsen.wxs wenxingsen.wxs@antgroup.com https://gitcode.net/oceanbase/oblogmsg/-/commit/5f23754a7d41bd635873365fb3473ea9f1fda553 Merge branch rpmbuild into master 2022-10-11T20:17:33+08:00 xiaoyi.yl xiaoyi.yl@antfin.com Title: oblogmsg开源改造,支持打包 1、提供build.sh 编译体验和ob一致 2、使用dep_create.sh管理依赖 3、支持在效能团队平台进行打包 4、保存兼容性 ![](<a href="https://cn-hangzhou.oss-cdn.aliyun-inc.com/git/force/uploads/comment/280397/34287051255239672/image.png" rel="nofollow noreferrer noopener" target="_blank">https://cn-hangzhou.oss-cdn.aliyun-inc.com/git/force/uploads/comment/280397/34287051255239672/image.png</a>) Link: <a href="https://code.alibaba-inc.com/oceanbase-ce-publish/oblogmsg/codereview/10357812" rel="nofollow noreferrer noopener" target="_blank">https://code.alibaba-inc.com/oceanbase-ce-publish/oblogmsg/codereview/10357812</a> https://gitcode.net/oceanbase/oblogmsg/-/commit/62665708184e7be188b361119d8d6785ef37b760 add field 2022-10-17T18:15:32+08:00 自凡 wangxiantong.wxt@alibaba-inc.com https://gitcode.net/oceanbase/oblogmsg/-/commit/725fca7c4da1a49dfcd12defc077c74aad5e07ad add unit test 2022-10-17T18:19:33+08:00 自凡 wangxiantong.wxt@alibaba-inc.com https://gitcode.net/oceanbase/oblogmsg/-/commit/27b5f84706ff501b1987bae787e6311147805146 Merge branch add_field into master 2022-10-18T15:01:35+08:00 xiaoyi.yl xiaoyi.yl@antfin.com Title: add field 补充oblogmsg 3.3版本字段 Link: <a href="https://code.alibaba-inc.com/oceanbase-ce-publish/oblogmsg/codereview/10439774" rel="nofollow noreferrer noopener" target="_blank">https://code.alibaba-inc.com/oceanbase-ce-publish/oblogmsg/codereview/10439774</a> https://gitcode.net/oceanbase/oblogmsg/-/commit/a6363b5821801f5daa9edcf78bb3354ba9dfa7d5 stc bug fix 2022-11-08T16:21:33+08:00 自凡 wangxiantong.wxt@alibaba-inc.com https://gitcode.net/oceanbase/oblogmsg/-/commit/b5406db253da9f350880263c2f1245e27786719d add .secignore 2022-11-14T18:02:11+08:00 自凡 wangxiantong.wxt@alibaba-inc.com
---
Language: Cpp
# BasedOnStyle: LLVM
SortIncludes: false
AccessModifierOffset: -2
AlignAfterOpenBracket: DontAlign
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
DerivePointerAlignment: false
PointerAlignment: Left
ConstructorInitializerIndentWidth: 4
AlignEscapedNewlinesLeft: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: true
AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: false
AlwaysBreakBeforeMultilineStrings: false
BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BinPackParameters: true
ColumnLimit: 120
ConstructorInitializerAllOnOneLineOrOnePerLine: true
DerivePointerBinding: true
ExperimentalAutoDetectBinPacking: false
IndentCaseLabels: true
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCSpaceBeforeProtocolList: false
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 200
PenaltyBreakString: 1000
PenaltyBreakFirstLessLess: 120
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
PointerBindsToType: true
Cpp11BracedListStyle: true
Standard: Auto
IndentWidth: 2
TabWidth: 4
UseTab: Never
BreakBeforeBraces: Custom
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
IndentFunctionDeclarationAfterType: true
SpacesInParentheses: false
SpacesInAngles: false
SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false
SpaceAfterControlStatementKeyword: true
SpaceBeforeAssignmentOperators: true
SpacesBeforeTrailingComments: 2
ContinuationIndentWidth: 4
CommentPragmas: '^lint'
MacroBlockBegin: "
END_CATCH_ERROR$"
...
deps/3rd/
build
build_*/
\ No newline at end of file
[submodule "third_party/googletest"]
path = third_party/googletest
url = https://github.com/google/googletest.git
##########################################################
# OBFlow Secret Scan Ignore List #
##########################################################
# Above the segmentation lines there are suspected privacy information #
# Please use the file name as the first line and the igored information #
# should be started with space or tab #
# Under the segmentation lines there are the folders which you need to ignore #
##########################################################
**
https://github.com/oceanbase/oblogmsg.git
http://yum-test.obvos.alibaba-inc.com/oceanbase/development-kit/el/7/aarch64/
http://yum-test.obvos.alibaba-inc.com/oceanbase/development-kit/el/7/x86_64/
http://yum-test.obvos.alibaba-inc.com/oceanbase/development-kit/el/8/aarch64/
http://yum-test.obvos.alibaba-inc.com/oceanbase/development-kit/el/8/x86_64/
https://github.com/google/googletest.git
http://license.coscl.org.cn/MulanPSL2
http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
http://sourceforge.net/projects/slicing-by-8/
https://facebook.github.io/watchman/*
--------------------------------------------------------
\ No newline at end of file
cmake_minimum_required(VERSION 3.20.0)
if(BUILD_AS_MAIN_PROJECT)
message(STATUS "oblogmsg build as main project")
include(cmake/Utils.cmake)
include(cmake/Env.cmake)
else()
message(STATUS "oblogmsg build as sub project")
endif()
project(oblogmsg VERSION 3.2.1)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel ..." FORCE)
endif()
add_compile_definitions($<$<COMPILE_LANGUAGE:CXX>:_GLIBCXX_USE_CXX11_ABI=0>)
add_subdirectory(src)
# Check if oblogmsg is being used directly or via add_subdirectory
set(OBLOGMSG_MASTER_PROJECT OFF)
if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(OBLOGMSG_MASTER_PROJECT ON)
endif()
if(OBLOGMSG_MASTER_PROJECT)
message(STATUS "git submodule update --init third_party/googletest")
execute_process(COMMAND git submodule update --init third_party/googletest
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMAND_ERROR_IS_FATAL ANY)
set(BUILD_GMOCK OFF CACHE INTERNAL "Builds the googlemock subproject")
set(INSTALL_GTEST OFF CACHE INTERNAL "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)")
add_subdirectory(third_party/googletest)
add_subdirectory(unittest)
add_subdirectory(benchmark)
endif()
# If oblogmsg is used via add_subdirectory, by default we don't install it.
option(INSTALL_OBLOGMSG "Whether or not install oblogmsg" ${OBLOGMSG_MASTER_PROJECT})
if(INSTALL_OBLOGMSG)
################# INSTALL ##########################################################################
include(GNUInstallDirs)
install(DIRECTORY include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}
)
install(TARGETS oblogmsg_shared oblogmsg_static
EXPORT oblogmsg
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}
)
install(EXPORT oblogmsg
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/oblogmsg
FILE oblogmsg.cmake
NAMESPACE oceanbase::
)
## install oblogmsgConfig.cmake and oblogmsgConfigVersion.cmake
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/oblogmsgConfig.cmake "include(\${CMAKE_CURRENT_LIST_DIR}/oblogmsg.cmake)\n")
include(CMakePackageConfigHelpers)
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/oblogmsgConfigVersion.cmake
COMPATIBILITY SameMajorVersion
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/oblogmsgConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/oblogmsgConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/oblogmsg
)
################# PACKAGE ##########################################################################
set(CPACK_GENERATOR "RPM")
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
set(CPACK_COMPONENTS_IGNORE_GROUPS 1)
set(CPACK_RPM_COMPONENT_INSTALL ON)
set(CPACK_RPM_RELOCATION_PATHS /usr /home/admin/oceanbase)
set(CPACK_PACKAGING_INSTALL_PREFIX /home/admin/oceanbase)
set(CPACK_RPM_PACKAGE_GROUP "Applications/Databases")
set(CPACK_RPM_PACKAGE_LICENSE "Mulan PubL v2.")
set(CPACK_RPM_DEFAULT_USER "admin")
set(CPACK_RPM_DEFAULT_GROUP "admin")
set(CPACK_RPM_SPEC_MORE_DEFINE
"%global _missing_build_ids_terminate_build 0
%global _find_debuginfo_opts -g
%define __debug_install_post %{_rpmconfigdir}/find-debuginfo.sh %{?_find_debuginfo_opts} %{_builddir}/%{?buildsubdir};%{nil}
%define debug_package %{nil}")
include(CPack)
endif()
木兰宽松许可证, 第2版
2020年1月 http://license.coscl.org.cn/MulanPSL2
您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束:
0. 定义
“软件” 是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。
“贡献” 是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。
“贡献者” 是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。
“法人实体” 是指提交贡献的机构及其“关联实体”。
“关联实体” 是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。
1. 授予版权许可
每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。
2. 授予专利许可
每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。
3. 无商标许可
“本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。
4. 分发限制
您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。
5. 免责声明与责任限制
“软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。
6. 语言
“本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。
条款结束
Mulan Permissive Software License,Version 2 (Mulan PSL v2)
January 2020 http://license.coscl.org.cn/MulanPSL2
Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions:
0. Definition
Software means the program and related documents which are licensed under this License and comprise all Contribution(s).
Contribution means the copyrightable work licensed by a particular Contributor under this License.
Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License.
Legal Entity means the entity making a Contribution and all its Affiliates.
Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity.
1. Grant of Copyright License
Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not.
2. Grant of Patent License
Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken.
3. No Trademark License
No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in section 4.
4. Distribution Restriction
You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software.
5. Disclaimer of Warranty and Limitation of Liability
THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
6. Language
THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL.
END OF THE TERMS AND CONDITIONS
oblogmsg 是一种数据库增量数据的输出格式,oceanbase 的增量采集模块 liboblog 正是使用的这种消息格式来输出增量数据,oblogmsg 支持 oceanbase 中不同数据类型的增量数据的写入,具有序列化和反序列化的能力。
## 如何使用 oblogmsg
> 前置条件
>
> * cmake: >=3.20.0
> * g++: 支持 C++11 标准
### 以源码方式依赖(推荐方式)
* 可以使用 `git submodule` 的方式将 oblogmsg 作为主项目的子模块
* 在主项目的 CMakeLists.txt 文件中使用 `add_subdirectory(submodule_path_to_oblogmsg)` 来依赖 oblogmsg,该命令执行后将提供 `oceanbase::oblogmsg_shared``oceanbase::oblogmsg_static` 两个 targets
* 在主项目相关 CMakeLists.txt 文件中,对于要依赖 oblogmsg 的 target t1,使用 `target_link_libraries(t1 PRIVATE oceanbase::oblogmsg_shared)`或者 `target_link_libraries(t1 PRIVATE oceanbase::oblogmsg_static)`即可
### 依赖编译后的 oblogmsg 库
* 编译、安装 oblogmsg
```shell
# 编译 oblogmsg
git clone https://github.com/oceanbase/oblogmsg.git
mkdir oblogmsg-build
cd oblogmsg-build
cmake -S ../oblogmsg -B .
cmake --build .
# 本地安装
cmake --install . --prefix=${OBLOGMSG_INSTALL_PATH}
```
* 主项目中依赖编译、安装后的 oblogmsg
* 在主项目 CMakeLists.txt 文件中使用 `set(CMAKE_PREFIX_PATH $ENV{OBLOGMSG_INSTALL_PATH} ${CMAKE_PREFIX_PATH})` 设置 oblogmsg 库搜索路径
* 然后使用 `find_package(oblogmsg REQUIRED)`使加载 oblogmsg,该命令执行成功后将提供 `oceanbase::oblogmsg_shared``oceanbase::oblogmsg_static` 两个 targets
* 在主项目相关 CMakeLists.txt 文件中,对于要依赖 oblogmsg 的 target t1,使用 `target_link_libraries(t1 PRIVATE oceanbase::oblogmsg_shared)`或者 `target_link_libraries(t1 PRIVATE oceanbase::oblogmsg_static)`即可
## oblogmsg 部分接口说明
### 创建一个 record
1. void ILogRecord::setSrcType(int type)
功能描述:
设置数据源的类型
参数:
type 有效值有0x00,0x01,0x02,0x03,0x04,0x05,对应数据源分别是 MYSQL,OCEANBASE,HBASE,ORACLE,OCEANBASE_1_0,DB2,liboblog 设置的值是0x04,即数据源是 OCEANBASE_1_0
返回值:
无返回值
2. void ILogRecord::setCheckpoint(uint64_t file, uint64_t offset)
功能描述:
设置当前的分析位点信息
参数:
file 一个秒级的 unix 时间戳
offset file 参数中 unix 时间戳的微秒级
返回值:
无返回值
3. int ILogRecord::setRecordType(int aType)
功能描述:
设置一条 record 的操作类型
参数:
aType 一般有七种类型 插入操作0x00 (EINSERT),更新操作0x01 (EUPDATE),删除操作0x02 (EDELETE),心跳包0x04 (HEARTBEAT),事物开始0x06 (EBEGIN),事物提交0x07 (ECOMMIT), DDL 操作0x08 (EDDL)
返回值:
固定返回0
4. void ILogRecord::setDbname(const char *dbname)
功能描述:
设置一条 record 来源的 db 名字
参数:
dbname record 的来源的数据库名字
返回值:
无返回值
5. void ILogRecord::setTbname(const char *tbname)
功能描述:
设置一条 record 的 table 名字
参数:
dbname record 的表名
返回值:
无返回值
6. void ILogRecord::setTableMeta(ITableMeta* tblMeta)
功能描述:
设置一个 record 的元数据信息
参数:
tblMeta record 的元数据信息,内存需由调用方申请和释放
返回值:
无返回值
7. void ITableMeta::setName(const char* name)
功能描述:
设置元数据中的表名字
参数:
name 表的名字
返回值:
无返回值
8. void ITableMeta::setUKs(const char* uks)
功能描述:
设置元数据中的UK字段名字
参数:
uks 包含有 uk 字段的名字的字符串,格式为 (col1,col2,col3...),当有多个 uk 时,例如 (col1,col2),(col2,col3),需要合并成一个字符串 (col1,col2,col3) 传入
返回值:
无返回值
9. void ITableMeta::setPKs(const char* pks)
功能描述:
设置元数据中的 PK 字段名字
参数:
pks 包含 pk 字段的名字的一个字符串,格式为 (col1,col2,col3...)
返回值:
无返回值
10. void ITableMeta::setPkinfo(const char* info)
功能描述:
设置元数据中的 PK 字段 id
参数:
info 包含有 pk 字段 id 的一个字符串,格式为(0,1,2,3...),从0开始
返回值:
无返回值
11. void ITableMeta::setUkinfo(const char* info)
功能描述:
设置元数据中的 UK 字段 id
参数:
info 包含有 uk 字段 id 的一个字符串,格式为(0,1,2,3...),当有多个uk时,传入格式为(0,1),(1,2),(0,3)...
返回值:
无返回值
12. int ITableMeta::append(const char* colName, IColMeta* colMeta);
功能描述:
向一个表的元数据信息添加一个列的元数据信息
参数:
colName 列的名字
colMeta 列的元数据信息
返回值:
-1 此列名在表中已存在时,添加会失败,返回-1
0 添加成功
13. void IColMeta::setName(const char* name)
功能描述:
为一个列的元数据信息设置列名
参数:
name 此列的名字
返回值:
无返回值
14. void IColMeta::setType(int type)
功能描述:
设置列的类型
参数:
type 列的类型,可设置的值详见 include/MetaInfo.h 中的枚举类型 logmsg_field_types
返回值:
无返回值
15. void IColMeta::setLength(long length)
功能描述:
设置列的字节长度
参数:
length 该列的字节长度
返回值:
无返回值
16. void IColMeta::setIsPK(bool b)
功能描述:
设置该列是否时 pk
参数:
b 设置为 true 时,该列为 uk,false 时,该列不是 uk
返回值:
无返回值
17. void IColMeta::setIsUK(bool b)
功能描述:
设置该列是否时uk
参数:
b 设置为 true 时,该列为 uk,false 时,该列不是 uk
返回值:
无返回值
18. void IColMeta::setNotNull(bool b)
功能描述:
设置该列是否有非空约束
参数:
b 设置为 true 时,该列不能为空,false 时,该列可以为空
返回值:
无返回值
19. void ILogRecord::setOldColumn(BinLogBuf* buf, int size)
功能描述:
初始化一片空间用来存放前镜像的字段值,空间大小为 size 个 BinLogBuf 的大小,size 必须比大于等于表的字段数目,该空间由调用方申请和释放
参数:
buf 空间的首地址
size 空间中 BinLogBuf 的个数,一般为表的字段数目
返回值:
无返回值
20. void ILogRecord::setNewColumn(BinLogBuf* buf, int size)
功能描述:
初始化一片空间用来存放后镜像的字段值,空间大小为 size 个 BinLogBuf 的大小,size 必须比大于等于表的字段数目,该空间由调用方申请和释放
参数:
buf 空间的首地址
size 空间中 BinLogBuf 的个数,一般为表的字段数目
返回值:
无返回值
21. int ILogRecord::putOld(const char* pos, int len)
功能描述:
添加一个前镜像中字段的值到 record 中
参数:
pos 字段值的起始地址
len 字段值的长度
返回值:
固定返回0
22. int ILogRecord::putNew(const char* pos, int len)
功能描述:
添加一个后镜像中字段的值到 record 中
参数:
pos 字段值的起始地址
len 字段值的长度
返回值:
固定返回0
23. const char* ILogRecord::toString(size_t *size, bool reserveMemory)
功能描述:
序列化一个record
参数:
size 一个 size_t 类型的地址,序列化完成后,会将序列化后数据的长度写入该地址
reserveMemory 是否保留序列化之后的数据到 record 的数据区,若不保留,改 record 在序列化之后,里面所存储的数据会被清空,将不可用
返回值:
NULL 序列化失败
非空指针 序列化之后的数据首地址
24. ILogRecord::bool parsedOK()
功能描述:
获取一个 record 是否已经完成序列化
参数:
返回值:
true 此 record 已经完成序列化,或者此 record 是由一段数据反序列化后创建的
false 此 record 还未进行序列化
### 反序列化一个 record,或者从一个已经序列化过的 record 中( ILogRecord::parsedOK() 返回 true )解析数据
1. int ILogRecord::parse(const void* ptr, size_t size)
功能描述:
反序列化一个 record
参数:
ptr 保存着序列化数据的首地址
size 序列化数据的长度
返回值:
0 成功
其他值 失败
2. int ILogRecord::getSrcType()
功能描述:
获取数据源的类型
参数:
返回值:
返回一个int型数值,有效值有0x00,0x01,0x02,0x03,0x04,0x05,对应数据源分别是 MYSQL,OCEANBASE,HBASE,ORACLE,OCEANBASE_1_0,DB2,liboblog 设置的值是0x04,即数据源是 OCEANBASE_1_0
3. uint64_t ILogRecord::getCheckpoint1()/uint64_t ILogRecord::getCheckpoint2()
功能描述:
获取分析的位点信息
参数:
返回值:
getCheckpoint1:返回一个秒级的 unix 时间戳
getCheckpoint2:返回 unix 时间戳的微秒级,可利用 getCheckpoint1*1000000+getCheckpoint2 做为分析的断点位置
4. int ILogRecord::recordType()
功能描述:
获取一条 record 的操作类型
参数:
返回值:
返回一个int类型数值,一般有七种类型,插入操作0x00 (EINSERT),更新操作0x01 (EUPDATE),删除操作0x02 (EDELETE),心跳包0x04 (HEARTBEAT),事物开始0x06 (EBEGIN),事物提交0x07 (ECOMMIT),DDL 操作0x08 (EDDL)
5. const char* ILogRecord::dbname() const
功能描述:
获取一条 record 来源的 db 名字
参数:
返回值:
返回一个char*类型的指针,该指针指向 record 的来源的数据库名字
6. const char* ILogRecord::tbname() const
功能描述:
获取一条 record 的 table 名字
参数:
返回值:
返回一个 char* 类型的指针,该指针指向 record 的来源的表名字
7. int ILogRecord::getTableMeta(ITableMeta*& tblMeta)
功能描述:
从一个 record 获取表的元数据信息,从一个序列化过的 record 取值时,由调用方为 tblMeta 申请和释放内存
参数:
tblMeta 表元数据信息的首地址
返回值:
0 成功
其他值 失败
8. const char* ITableMeta::getName()
功能描述:
获取元数据中的表名字
参数:
name 表的名字
返回值:
返回一个 char* 类型的指针,该指针指向 record 的元数据中的表名字
9. const char* ITableMeta::getUKs()
功能描述:
获取元数据中的 UK 字段名字
参数:
返回值:
返回一个 char* 指针,指向包含有 uk 字段的名字的字符串,格式为 (col1,col2,col3...)
10. const char* ITableMeta::getPKs()
功能描述:
获取元数据中的 PK 字段名字
参数:
返回值:
返回一个 char* 指针,指向包含 pk 字段的名字的一个字符串,格式为 (col1,col2,col3...)
11. const char* ITableMeta::getPkinfo()
功能描述:
获取元数据中的 PK 字段 id,从0开始
参数:
返回值:
返回一个 char* 指针,指向包含有 pk 字段 id 的一个字符串,格式为 (0,1,2,3...)
12. const char* ITableMeta::getUkinfo()
功能描述:
设置元数据中的 PK 字段 id,从0开始
参数:
返回值:
返回一个 char* 指针,指向包含有 uk 字段 id 的一个字符串,格式为(0,1,2,3...)
13. int ITableMeta::getColCount()
功能描述:
获取元数据中的字段数量
参数:
返回值:
返回字段的数量
14. const char* IColMeta::getName()
功能描述:
获取一个列的元数据中的列名
参数:
返回值:
返回一个 char* 指针,指向元数据的列名
15. int IColMeta::getType()
功能描述:
获取列的类型
参数:
返回值:
返回一个 int 型数值,详见 include/MetaInfo.h 中的枚举类型 logmsg_field_types
16. long IColMeta::getLength()
功能描述:
获取列的字节长度
参数:
返回值:
列的字节长度
17. bool IColMeta::isPK()
功能描述:
获取该列是否时 pk
参数:
返回值:
返回一个 bool 类型,为 true 时,该列为 uk,false 时,该列不是 uk
18. bool IColMeta::isUK()
功能描述:
获取该列是否时 uk
参数:
返回值:
返回一个 bool 类型,为 true 时,该列为 uk,false 时,该列不是 uk
19. bool IColMeta::isNotNull()
功能描述:
获取该列是否有非空约束
参数:
返回值:
返回一个 bool 类型,为 true 时,该列有非空约束,false 时,该列可以为空
20. StrArray* ILogRecord::parsedOldCols() const
功能描述:
获取 record 中前镜像的所有字段值
参数:
返回值:
返回一个 StrArray 类型的指针,该指针指向存着前镜像的值,可通过 StrArray->size() 接口获取数据的列数,StrArray->elementAt(int i, const char*& s, size_t& length) 接口获取每列的数据
21. StrArray* ILogRecord::parsedNewCols() const
功能描述:
获取 record 中后镜像的所有字段值
参数:
返回值:
返回一个 StrArray 类型的指针,该指针指向存着后镜像的值,可通过 StrArray->size() 接口获取数据的列数,StrArray->elementAt(int i, const char*& s, size_t& length) 接口获取每列的数据
### 从一个未序列化过的 record 中( ILogRecord::parsedOK() 返回 false )解析前后镜像字段的数据
1. int ILogRecord::getTableMeta(ITableMeta*& tblMeta)
功能描述:
从一个 record 获取表的元数据信息,从一个未序列化过的 record 取值时,tblMeta 必须为一个空指针
参数:
tblMeta 需为一个空指针,该接口会将此指针指向 record 的元数据地址,内存由 oblogmsg 管理,调用方不需要释放
返回值:
0 成功
其他值 失败
2. BinLogBuf* ILogRecord::newCols(unsigned int& count)
功能描述:
获取 record 中后镜像的所有字段值
参数:
count 用来返回数据的列数
返回值:
返回一个 BinLogBuf 类型的指针,该指针指向一个拥有 count 个 BinLogBuf 的空间,每个 BinLogBuf.buf 成员即是字段的值,BinLogBuf.buf_used_size 为字段值的长度
3. BinLogBuf* ILogRecord::oldCols(unsigned int& count)
功能描述:
获取 record 中后镜像的所有字段值
参数:
count 用来返回数据的列数
返回值:
返回一个 BinLogBuf 类型的指针,该指针指向一个拥有 count 个 BinLogBuf 的空间,每个 BinLogBuf.buf 成员即是字段的值,BinLogBuf.buf_used_size 为字段值的长度
add_executable(lmTest itoa.cpp lmTest.cpp)
target_compile_definitions(lmTest PRIVATE LMB)
target_include_directories(lmTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(lmTest PRIVATE oblogmsg_shared)
#include <cstdint>
static uint16_t MAT[] = {0x3030,
0x3130,
0x3230,
0x3330,
0x3430,
0x3530,
0x3630,
0x3730,
0x3830,
0x3930,
0x3031,
0x3131,
0x3231,
0x3331,
0x3431,
0x3531,
0x3631,
0x3731,
0x3831,
0x3931,
0x3032,
0x3132,
0x3232,
0x3332,
0x3432,
0x3532,
0x3632,
0x3732,
0x3832,
0x3932,
0x3033,
0x3133,
0x3233,
0x3333,
0x3433,
0x3533,
0x3633,
0x3733,
0x3833,
0x3933,
0x3034,
0x3134,
0x3234,
0x3334,
0x3434,
0x3534,
0x3634,
0x3734,
0x3834,
0x3934,
0x3035,
0x3135,
0x3235,
0x3335,
0x3435,
0x3535,
0x3635,
0x3735,
0x3835,
0x3935,
0x3036,
0x3136,
0x3236,
0x3336,
0x3436,
0x3536,
0x3636,
0x3736,
0x3836,
0x3936,
0x3037,
0x3137,
0x3237,
0x3337,
0x3437,
0x3537,
0x3637,
0x3737,
0x3837,
0x3937,
0x3038,
0x3138,
0x3238,
0x3338,
0x3438,
0x3538,
0x3638,
0x3738,
0x3838,
0x3938,
0x3039,
0x3139,
0x3239,
0x3339,
0x3439,
0x3539,
0x3639,
0x3739,
0x3839,
0x3939};
int I2A_64(uint64_t i, char* a)
{
if (i < (uint64_t)1000000000000) {
if (i < 100000000) {
uint32_t _i = i;
if (_i < 10) {
*a = _i + '0';
return 1;
} else if (_i < 100) {
*(uint16_t*)a = MAT[_i];
return 2;
} else if (_i < 10000) {
uint16_t A = _i / 100, B = _i - A * 100;
if (i < 1000) {
*a = A + '0';
*(uint16_t*)&a[1] = MAT[B];
return 3;
} else {
*(uint16_t*)&a[2] = MAT[B];
*(uint16_t*)a = MAT[A];
return 4;
}
} else {
uint16_t A = _i / 10000, B = _i - A * 10000, C = B / 100, D = B - C * 100;
if (A >= 100) {
/*12345678*/
if (A >= 1000) {
*(uint16_t*)a = MAT[A / 100];
*(uint16_t*)&a[2] = MAT[A % 100];
*(uint16_t*)&a[4] = MAT[C];
*(uint16_t*)&a[6] = MAT[D];
return 8;
} else {
*a = A / 100 + '0';
*(uint16_t*)&a[1] = MAT[A % 100];
*(uint16_t*)&a[3] = MAT[C];
*(uint16_t*)&a[5] = MAT[D];
return 7;
}
} else {
if (A >= 10) {
*(uint16_t*)a = MAT[A];
*(uint16_t*)&a[2] = MAT[C];
*(uint16_t*)&a[4] = MAT[D];
return 6;
} else {
*a = A + '0';
*(uint16_t*)&a[1] = MAT[C];
*(uint16_t*)&a[3] = MAT[D];
return 5;
}
}
}
} else {
uint8_t len;
uint32_t A = i / 100000000;
if (A < 10) {
*a = A + '0';
len = 1;
} else if (A < 100) {
*(uint16_t*)a = MAT[A];
len = 2;
} else if (A < 1000) {
uint16_t B = ((uint16_t)A) / 100;
*a = B + '0';
*(uint16_t*)(a + 1) = MAT[A - B * 100];
len = 3;
} else {
uint16_t B = ((uint16_t)A) / 100;
*(uint16_t*)a = MAT[B];
*(uint16_t*)(a + 2) = MAT[A - B * 100];
len = 4;
}
uint32_t _A = i - A * 100000000;
char* p = a + len;
uint16_t C;
uint16_t H = _A / 10000, L = _A - 10000 * H;
C = H / 100;
*(uint16_t*)p = MAT[C];
*(uint16_t*)(p + 2) = MAT[H - 100 * C];
C = L / 100;
*(uint16_t*)(p + 4) = MAT[C];
*(uint16_t*)(p + 6) = MAT[L - 100 * C];
return len + 8;
}
}
// 64bit max is 1844 6744 0737 0955 1615
else {
uint32_t H = i / (uint64_t)1000000000000;
unsigned char l = 0;
if (H < 100) {
if (H < 10) {
*a = H + '0';
l = 1;
} else {
*(uint16_t*)a = MAT[H];
l = 2;
}
} else if (H < 10000) {
if (H < 1000) {
*a = H / 100 + '0';
*(uint16_t*)(a + 1) = MAT[H % 100];
l = 3;
} else {
*(uint16_t*)(a) = MAT[H / 100];
*(uint16_t*)(a + 2) = MAT[H % 100];
l = 4;
}
} else if (H < 1000000) {
if (H < 100000) {
uint16_t v = H / 10000;
*a = v + '0';
v = H - 10000 * v;
*(uint16_t*)(a + 1) = MAT[v / 100];
*(uint16_t*)(a + 3) = MAT[v % 100];
l = 5;
} else {
uint16_t v = H / 10000;
*(uint16_t*)(a) = MAT[v];
v = H - 10000 * v;
*(uint16_t*)(a + 2) = MAT[v / 100];
*(uint16_t*)(a + 4) = MAT[v % 100];
l = 6;
}
} else {
if (H < 10000000) {
uint16_t v = H / 10000;
*a = v / 100 + '0';
*(uint16_t*)(a + 1) = MAT[v % 100];
v = H - 10000 * v;
*(uint16_t*)(a + 3) = MAT[v / 100];
*(uint16_t*)(a + 5) = MAT[v % 100];
l = 7;
} else {
uint16_t v = H / 10000;
*(uint16_t*)(a) = MAT[v / 100];
*(uint16_t*)(a + 2) = MAT[v % 100];
v = H - 10000 * v;
*(uint16_t*)(a + 4) = MAT[v / 100];
*(uint16_t*)(a + 6) = MAT[v % 100];
l = 8;
}
}
uint64_t L = i - (uint64_t)1000000000000 * H;
/* if(L==0)
{
memcpy(a+l,0,12);
return l+12;
}*/
uint16_t v = L / 100000000;
char* p = a + l;
uint16_t v1 = v / 100;
((uint16_t*)(p))[0] = MAT[v1];
((uint16_t*)p)[1] = MAT[v - 100 * v1];
uint32_t L1 = L - ((uint64_t)100000000) * v;
v = L1 / 10000;
v1 = v / 100;
((uint16_t*)p)[2] = MAT[v1];
((uint16_t*)p)[3] = MAT[v - 100 * v1];
v = L1 - v * 10000;
v1 = v / 100;
((uint16_t*)p)[4] = MAT[v1];
((uint16_t*)p)[5] = MAT[v - 100 * v1];
return l + 12;
}
}
int I2A_32(uint32_t i, char* a)
{
if (i < 100000000) {
uint32_t _i = i;
if (_i < 10) {
*a = _i + '0';
return 1;
} else if (_i < 100) {
*(uint16_t*)a = MAT[_i];
return 2;
} else if (_i < 10000) {
uint16_t A = _i / 100, B = _i - A * 100;
if (i < 1000) {
*a = A + '0';
*(uint16_t*)&a[1] = MAT[B];
return 3;
} else {
*(uint16_t*)&a[2] = MAT[B];
*(uint16_t*)a = MAT[A];
return 4;
}
} else {
uint16_t A = _i / 10000, B = _i - A * 10000, C = B / 100, D = B - C * 100;
if (A >= 100) {
/*12345678*/
if (A >= 1000) {
*(uint16_t*)a = MAT[A / 100];
*(uint16_t*)&a[2] = MAT[A % 100];
*(uint16_t*)&a[4] = MAT[C];
*(uint16_t*)&a[6] = MAT[D];
return 8;
} else {
*a = A / 100 + '0';
*(uint16_t*)&a[1] = MAT[A % 100];
*(uint16_t*)&a[3] = MAT[C];
*(uint16_t*)&a[5] = MAT[D];
return 7;
}
} else {
if (A >= 10) {
*(uint16_t*)a = MAT[A];
*(uint16_t*)&a[2] = MAT[C];
*(uint16_t*)&a[4] = MAT[D];
return 6;
} else {
*a = A + '0';
*(uint16_t*)&a[1] = MAT[C];
*(uint16_t*)&a[3] = MAT[D];
return 5;
}
}
}
} else {
uint8_t len;
uint32_t A = i / 100000000;
if (A < 10) {
*a = A + '0';
len = 1;
} else {
*(uint16_t*)a = MAT[A];
len = 2;
}
uint32_t _A = i - A * 100000000;
char* p = a + len;
uint16_t C;
uint16_t H = _A / 10000, L = _A - 10000 * H;
C = H / 100;
*(uint16_t*)p = MAT[C];
*(uint16_t*)(p + 2) = MAT[H - 100 * C];
C = L / 100;
*(uint16_t*)(p + 4) = MAT[C];
*(uint16_t*)(p + 6) = MAT[L - 100 * C];
return len + 8;
}
}
int I2A_16(uint16_t i, char* a)
{
if (i < 10) {
*a = i + '0';
return 1;
} else if (i < 100) {
*(uint16_t*)a = MAT[i];
return 2;
} else if (i < 10000) {
uint16_t A = i / 100, B = i - A * 100;
if (i < 1000) {
*a = A + '0';
*(uint16_t*)&a[1] = MAT[B];
return 3;
} else {
*(uint16_t*)&a[2] = MAT[B];
*(uint16_t*)a = MAT[A];
return 4;
}
} else {
uint8_t A = i / 10000;
uint16_t B = i - 10000 * A;
*a = A + '0';
*(uint16_t*)&a[1] = MAT[B / 100];
*(uint16_t*)&a[3] = MAT[B % 100];
return 5;
}
}
/*
* itoa.h
*
* Created on: 2015��8��18��
* Author: liwei
*/
#ifndef _ITOA_H_
#define _ITOA_H_
#include <cstdint>
int I2A_16(uint16_t i, char* a);
int I2A_32(uint32_t i, char* a);
int I2A_64(uint64_t i, char* a);
#define sitoa(i, a) ((i >= 0) ? I2A_16(i, a) : (a[0] = '-', 1 + I2A_16(~(i) + 1, a + 1)))
#define sutoa(i, a) I2A_16(i, a)
#define itoa(i, a) ((i >= 0) ? I2A_32(i, a) : (a[0] = '-', 1 + I2A_32(~(i) + 1, a + 1)))
#define utoa(i, a) I2A_32(i, a)
#define ltoa(i, a) ((i >= 0) ? I2A_64(i, a) : (a[0] = '-', 1 + I2A_64(~(i) + 1, a + 1)))
#define ultoa(i, a) I2A_64(i, a)
#endif /* _ITOA_H_ */
此差异已折叠。
#!/bin/sh
TOPDIR=`readlink -f \`dirname $0\``
BUILD_SH=$TOPDIR/build.sh
ALL_ARGS=("$@")
DEP_DIR=${TOPDIR}/deps/3rd/usr/local/oceanbase/deps/devel
TOOLS_DIR=${TOPDIR}/deps/3rd/usr/local/oceanbase/devtools
CMAKE_COMMAND="${TOOLS_DIR}/bin/cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DBUILD_AS_MAIN_PROJECT=ON"
echo "$0 ${ALL_ARGS[@]}"
CPU_CORES=`grep -c ^processor /proc/cpuinfo`
NEED_INIT=false
NEED_MAKE=false
MAKE_ARGS=(-j $CPU_CORES)
# parse arguments
function parse_args
{
for i in "${ALL_ARGS[@]}"; do
if [[ "$i" == "--init" ]]
then
NEED_INIT=true
elif [[ "$i" == "--make" ]]
then
NEED_MAKE=make
elif [[ $NEED_MAKE == false ]]
then
BUILD_ARGS+=("$i")
else
MAKE_ARGS+=("$i")
fi
done
}
function usage
{
echo -e "Usage:
\t./build.sh -h
\t./build.sh init
\t./build.sh clean
\t./build.sh [BuildType] [--init] [--make [MakeOptions]]
OPTIONS:
BuildType => debug(default), release, errsim, dissearray, rpm
MakeOptions => Options to make command, default: -j N
Examples:
\t# Build by debug mode and make with -j24.
\t./build.sh debug --make -j24
"
}
# try call init if --init given.
function try_init
{
if [[ $NEED_INIT == true ]]
then
do_init || exit $?
fi
}
# try call command make, if use give --make in command line.
function try_make
{
if [[ $NEED_MAKE != false ]]
then
$NEED_MAKE "${MAKE_ARGS[@]}"
fi
}
# dep_create.sh
function do_init
{
(cd $TOPDIR/deps/3rd && bash dep_create.sh)
}
# create build directory and cd it.
function prepare_build_dir
{
TYPE=$1
mkdir -p $TOPDIR/build_$TYPE && cd $TOPDIR/build_$TYPE
}
# make build directory && cmake && make (if need)
function do_build
{
TYPE=$1; shift
prepare_build_dir $TYPE || return
${CMAKE_COMMAND} ${TOPDIR} "$@"
}
# clean build directories
function do_clean
{
echo "cleaning..."
find . -maxdepth 1 -type d -name 'build_*' | xargs rm -rf
}
function build
{
set -- "${BUILD_ARGS[@]}"
case "x$1" in
xrelease)
do_build "$@" -DCMAKE_BUILD_TYPE=RelWithDebInfo
;;
xdebug)
do_build "$@" -DCMAKE_BUILD_TYPE=Debug
;;
*)
BUILD_ARGS=(debug "${BUILD_ARGS[@]}")
build
;;
esac
}
function main
{
case "$1" in
-h)
usage
;;
init)
do_init
;;
clean)
do_clean
;;
*)
parse_args
try_init
build
try_make
;;
esac
}
main "$@"
ob_define(DEVTOOLS_DIR "${CMAKE_SOURCE_DIR}/deps/3rd/usr/local/oceanbase/devtools")
ob_define(DEP_DIR "${CMAKE_SOURCE_DIR}/deps/3rd/usr/local/oceanbase/deps/devel")
set(CMAKE_C_COMPILER "${DEVTOOLS_DIR}/bin/gcc")
set(CMAKE_CXX_COMPILER "${DEVTOOLS_DIR}/bin/g++")
macro(ob_define VAR DEFAULT)
if (NOT DEFINED ${VAR})
set(${VAR} ${DEFAULT})
endif()
endmacro()
\ No newline at end of file
#!/bin/bash
#clear env
unalias -a
PWD="$(cd $(dirname $0); pwd)"
OS_ARCH="$(uname -m)" || exit 1
OS_RELEASE="0"
if [[ ! -f /etc/os-release ]]; then
echo "[ERROR] os release info not found" 1>&2 && exit 1
fi
source /etc/os-release || exit 1
PNAME=${PRETTY_NAME:-"${NAME} ${VERSION}"}
PNAME="${PNAME} (${OS_ARCH})"
function compat_centos8() {
echo "[NOTICE] '$PNAME' is compatible with CentOS 8, use el8 dependencies list"
OS_RELEASE=8
}
function compat_centos7() {
echo "[NOTICE] '$PNAME' is compatible with CentOS 7, use el7 dependencies list"
OS_RELEASE=7
}
function not_supported() {
echo "[ERROR] '$PNAME' is not supported yet."
}
function version_ge() {
test "$(awk -v v1=$VERSION_ID -v v2=$1 'BEGIN{print(v1>=v2)?"1":"0"}' 2>/dev/null)" == "1"
}
function get_os_release() {
if [[ "${OS_ARCH}x" == "x86_64x" ]]; then
case "$ID" in
alinux)
version_ge "2.1903" && compat_centos7 && return
;;
alios)
version_ge "8.0" && compat_centos8 && return
version_ge "7.2" && compat_centos7 && return
;;
anolis)
version_ge "8.0" && compat_centos8 && return
version_ge "7.0" && compat_centos7 && return
;;
ubuntu)
version_ge "16.04" && compat_centos7 && return
;;
centos)
version_ge "8.0" && OS_RELEASE=8 && return
version_ge "7.0" && OS_RELEASE=7 && return
;;
debian)
version_ge "9" && compat_centos7 && return
;;
fedora)
version_ge "33" && compat_centos7 && return
;;
opensuse-leap)
version_ge "15" && compat_centos7 && return
;;
#suse
sles)
version_ge "15" && compat_centos7 && return
;;
uos)
version_ge "20" && compat_centos7 && return
;;
arch)
compat_centos8 && return
;;
rocky)
version_ge "8.0" && compat_centos8 && return
;;
esac
elif [[ "${OS_ARCH}x" == "aarch64x" ]]; then
case "$ID" in
alios)
version_ge "8.0" && compat_centos8 && return
version_ge "7.0" && compat_centos7 && return
;;
centos)
version_ge "8.0" && OS_RELEASE=8 && return
version_ge "7.0" && OS_RELEASE=7 && return
;;
esac
elif [[ "${OS_ARCH}x" == "sw_64x" ]]; then
case "$ID" in
UOS)
version_ge "20" && OS_RELEASE=20 && return
;;
esac
fi
not_supported && return 1
}
get_os_release || exit 1
OS_TAG="el$OS_RELEASE.$OS_ARCH"
DEP_FILE="logmessage.${OS_TAG}.deps"
echo -e "check dependencies profile for ${DEP_FILE}... \c"
if [[ ! -f "${DEP_FILE}" ]]; then
echo "NOT FOUND" 1>&2
exit 2
else
echo "FOUND"
fi
mkdir "${PWD}/pkg" >/dev/null 2>&1
declare -A targets
declare -A packages
section="default"
content=""
function save_content {
if [[ "$content" != "" ]]
then
if [[ $(echo "$section" | grep -E "^target\-") != "" ]]
then
target_name=$(echo $section | sed 's|^target\-\(.*\)$|\1|g')
targets["$target_name"]="$(echo "${content}" | grep -Eo "repo=.*" | awk -F '=' '{ print $2 }')"
echo "target: $target_name, repo: ${targets["$target_name"]}"
else
packages["$section"]=$content
fi
fi
}
echo -e "check repository address in profile..."
while read -r line
do
if [[ $(echo "$line" | grep -E "\[.*\]") != "" ]]
then
save_content
content=""
# section=${line//\[\(.*\)\]/\1}
section=$(echo $line | sed 's|.*\[\(.*\)\].*|\1|g')
else
[[ "$line" != "" ]] && [[ "$line" != '#'* ]] && content+=$'\n'"$line"
fi
done < $DEP_FILE
save_content
# 删除旧依赖
ls |grep -v dep_create.sh |grep -v .deps |grep -v pkg |xargs rm -rf
echo "download dependencies..."
for sect in "${!packages[@]}"
do
#if [[ "$1" != "all" ]]
#then
# [[ "$sect" == "test-utils" ]] && continue
#fi
echo "${packages["$sect"]}" | while read -r line
do
[[ "$line" == "" ]] && continue
pkg=${line%%\ *}
target_name="default"
temp=$(echo "$line" | grep -Eo "target=(\S*)")
[[ "$temp" != "" ]] && target_name=${temp#*=}
if [[ -f "${PWD}/pkg/${pkg}" ]]; then
echo "find package <${pkg}> in cache"
else
echo -e "download package <${pkg}>... \c"
repo=${targets["$target_name"]}
TEMP=$(mktemp -p "/" -u ".${pkg}.XXXX")
wget "$repo/${pkg}" -q -O "${PWD}/pkg/${TEMP}"
if (( $? == 0 )); then
mv -f "${PWD}/pkg/$TEMP" "${PWD}/pkg/${pkg}"
echo "SUCCESS"
else
rm -rf "${PWD}/pkg/$TEMP"
echo "FAILED" 1>&2
exit 4
fi
fi
echo -e "unpack package <${pkg}>... \c"
if [ "$ID" = "arch" ]; then
rpmextract.sh "${PWD}/pkg/${pkg}"
else
rpm2cpio "${PWD}/pkg/${pkg}" | cpio -di -u --quiet
fi
if [[ $? -eq 0 ]]; then
echo "SUCCESS"
else
echo "FAILED" 1>&2
exit 5
fi
done
done
[target-default]
os=7
arch=aarch64
repo=http://yum-test.obvos.alibaba-inc.com/oceanbase/development-kit/el/7/aarch64/
[tools]
obdevtools-cmake-3.22.1-1.el7.aarch64.rpm
obdevtools-gcc9-9.3.0-52022092914.el7.aarch64.rpm
[target-default]
os=7
arch=x86_64
repo=http://yum-test.obvos.alibaba-inc.com/oceanbase/development-kit/el/7/x86_64/
[tools]
obdevtools-cmake-3.22.1-1.el7.x86_64.rpm
obdevtools-gcc9-9.3.0-52022092914.el7.x86_64.rpm
[target-default]
os=7
arch=aarch64
repo=http://yum-test.obvos.alibaba-inc.com/oceanbase/development-kit/el/8/aarch64/
[tools]
obdevtools-cmake-3.22.1-1.el8.aarch64.rpm
obdevtools-gcc9-9.3.0-52022092914.el8.aarch64.rpm
[target-default]
os=7
arch=x86_64
repo=http://yum-test.obvos.alibaba-inc.com/oceanbase/development-kit/el/8/x86_64/
[tools]
obdevtools-cmake-3.22.1-1.el8.x86_64.rpm
obdevtools-gcc9-9.3.0-52022092914.el8.x86_64.rpm
#!/bin/bash
set -e
ROOT=$(git rev-parse --show-toplevel)
ln -sf $ROOT/git-hooks/pre-commit $ROOT/.git/hooks/pre-commit
echo "installed git-hooks/pre-commit to .git/hooks/pre-commit"
#!/bin/bash
set -e
ROOT=$(git rev-parse --show-toplevel)
CLANG_FORMAT_HOOK_SCRIPT=$ROOT/git-hooks/pre-commit-clang-format
$CLANG_FORMAT_HOOK_SCRIPT
#!/bin/bash
CLANG_FORMAT=`which clang-format`
SOURCE_FILE_EXTS=(.h .hh .hpp .hxx .c .cc .cpp .cxx)
check_clang_format() {
if [ ! -x "$CLANG_FORMAT" ] ; then
echo "ERROR: clang-format executable not found."
exit 1
fi
}
# check whether the given file matches any of the extensions: case insensitive
matches_extension() {
local file_name=$(basename "$1")
local file_ext=".${file_name##*.}"
local lowercase_file_ext=`echo $file_ext | awk '{print tolower($0)}'`
local source_file_ext
for source_file_ext in "${SOURCE_FILE_EXTS[@]}"
do
local lowercase_source_file_ext=`echo $source_file_ext | awk '{print tolower($0)}'`
[[ "$lowercase_file_ext" = "$lowercase_source_file_ext" ]] && return 0
done
return 1
}
_FORMATTED_FILES_CNT=0
format_file() {
local source_file=$1
local formatted_file="${source_file}.formatted"
$CLANG_FORMAT -style=file $source_file > $formatted_file
cmp -s $source_file $formatted_file
if [ $? -ne 0 ]
then
mv $formatted_file $source_file && echo "formatted file $source_file"
let _FORMATTED_FILES_CNT++
else
rm -f $formatted_file
fi
}
_ROOT=$(git rev-parse --show-toplevel)
format_staged_source_files() {
for file in $(git diff --staged --name-only)
do
file=$_ROOT/$file
matches_extension $file && format_file $file
done
}
# return 1 if there was any file actually formatted, which will break the `git commit` process.
verify_format() {
if [ ${_FORMATTED_FILES_CNT} -gt 0 ]
then
echo "${_FORMATTED_FILES_CNT} files has been formatted."
exit 1
fi
}
main() {
check_clang_format
format_staged_source_files
verify_format
}
main
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
oblogmsg is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
#pragma once
#define LOG_EVENT_INIT_LEN (1024 * 32)
#include <cstdlib>
#include <cstring>
namespace oceanbase {
namespace logmessage {
struct BinLogBuf {
char* buf;
size_t buf_size;
size_t buf_used_size;
bool needFree;
BinLogBuf()
{
buf = NULL;
buf_size = buf_used_size = 0;
needFree = false;
}
BinLogBuf(char* binlog, size_t len)
{
buf = binlog;
buf_size = len;
buf_used_size = 0;
needFree = false;
}
~BinLogBuf()
{
if (buf != NULL && needFree == true)
delete[] buf;
}
};
static inline int set_binlogBuf(BinLogBuf* buf, char* binlog, size_t len)
{
bool needRealloc = true;
if (buf->buf == NULL) {
len > LOG_EVENT_INIT_LEN ? (buf->buf_size = len) : (buf->buf_size = LOG_EVENT_INIT_LEN);
} else if (buf->buf_size < len) {
buf->buf_size = len;
delete[] buf->buf;
} else if (LOG_EVENT_INIT_LEN > len && buf->buf_size > LOG_EVENT_INIT_LEN) {
buf->buf_size = LOG_EVENT_INIT_LEN;
delete[] buf->buf;
} else
needRealloc = false;
if (needRealloc) {
if ((buf->buf = new char[buf->buf_size]) == NULL)
return -1;
}
buf->needFree = true;
memcpy(buf->buf, binlog, len);
buf->buf_used_size = len;
return 0;
}
static inline void exchange_binlogBuf(BinLogBuf* buf, char* binlog, size_t len, size_t buf_used_size = 0)
{
if (buf->needFree == true)
delete[] buf->buf;
buf->buf = binlog;
buf->buf_size = len;
buf->buf_used_size = buf_used_size;
buf->needFree = false;
}
static inline void exchange_binlogBuf(BinLogBuf* buf, BinLogBuf* ebuf)
{
if (buf->needFree == true)
delete[] buf->buf;
if (ebuf == NULL) {
buf->buf = NULL;
buf->buf_size = buf->buf_used_size = 0;
return;
}
buf->buf = ebuf->buf;
ebuf->buf = NULL;
buf->buf_size = ebuf->buf_size;
ebuf->buf_size = 0;
buf->buf_used_size = ebuf->buf_used_size;
ebuf->buf_used_size = 0;
buf->needFree = ebuf->needFree;
ebuf->needFree = false;
}
static inline void get_binlogBuf(BinLogBuf* buf, char* binlog, size_t len)
{
if (buf->needFree == true)
delete[] buf->buf;
buf->buf = binlog;
buf->buf_used_size = buf->buf_size = len;
buf->needFree = false;
}
static inline int create_binlogBuf(BinLogBuf* buf, size_t len = LOG_EVENT_INIT_LEN)
{
if (NULL == (buf->buf = new char[buf->buf_size = len]))
return -1;
buf->needFree = true;
return (int)(buf->buf_used_size = 0);
}
static inline void clear_binlogBuf(BinLogBuf* buf)
{
buf->buf_used_size = 0;
}
static inline bool binlogBuf_NULL(BinLogBuf* buf)
{
return buf->buf == NULL;
}
} // namespace logmessage
} // namespace oceanbase
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
oblogmsg is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
#pragma once
namespace oceanbase {
namespace logmessage {
/* This should catch all modern GCCs and Clang */
#if (defined __BYTE_ORDER__) && (defined __ORDER_LITTLE_ENDIAN__)
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define ENDIANNESS_LE 1
#define ENDIANNESS_BE 0
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define ENDIANNESS_LE 0
#define ENDIANNESS_BE 1
#endif
/* Try to derive from arch/compiler-specific macros */
#elif defined(_X86_) || defined(__x86_64__) || defined(__i386__) || defined(__i486__) || defined(__i586__) || \
defined(__i686__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) || defined(__ARMEL__) || \
(defined(__LITTLE_ENDIAN__) && __LITTLE_ENDIAN__ == 1) || (defined(_LITTLE_ENDIAN) && _LITTLE_ENDIAN == 1) || \
defined(_M_IX86) || defined(_M_AMD64) /* MSVC */
#define ENDIANNESS_LE 1
#define ENDIANNESS_BE 0
#elif defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) || defined(__MICROBLAZEEB__) || defined(__ARMEB__) || \
(defined(__BIG_ENDIAN__) && __BIG_ENDIAN__ == 1) || (defined(_BIG_ENDIAN) && _BIG_ENDIAN == 1)
#define ENDIANNESS_LE 0
#define ENDIANNESS_BE 1
/* Try to get it from a header */
#else
#if defined(__linux)
#include <endian.h>
#else
#include <machine/endian.h>
#endif
#endif
#ifndef ENDIANNESS_LE
#undef ENDIANNESS_BE
#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN)
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define ENDIANNESS_LE 1
#define ENDIANNESS_BE 0
#elif __BYTE_ORDER == __BIG_ENDIAN
#define ENDIANNESS_LE 0
#define ENDIANNESS_BE 1
#endif
#elif defined(BYTE_ORDER) && defined(LITTLE_ENDIAN)
#if BYTE_ORDER == LITTLE_ENDIAN
#define ENDIANNESS_LE 1
#define ENDIANNESS_BE 0
#elif BYTE_ORDER == BIG_ENDIAN
#define ENDIANNESS_LE 0
#define ENDIANNESS_BE 1
#endif
#endif
#endif
/* In case the user passed one of -DENDIANNESS_LE or BE in CPPFLAS,
* set the second one too */
#if defined(ENDIANNESS_LE) && !(defined(ENDIANNESS_BE))
#if ENDIANNESS_LE == 0
#define ENDIANNESS_BE 1
#else
#define ENDIANNESS_BE 0
#endif
#elif defined(ENDIANNESS_BE) && !(defined(ENDIANNESS_LE))
#if ENDIANNESS_BE == 0
#define ENDIANNESS_LE 1
#else
#define ENDIANNESS_LE 0
#endif
#endif
#if !(defined(ENDIANNESS_LE)) && !(defined(ENDIANNESS_PORTABLE_CONVERSION))
#error \
"Sorry, we couldn't detect endiannes for your system! Please set -DENDIANNESS_LE=1 or 0 using your CPPFLAGS/CFLAGS!"
#endif
/*little endian set and get*/
static inline uint8_t swap8(uint8_t __x)
{
return __x;
}
static inline uint16_t swap16(uint16_t __x)
{
return (__x << 8) | (__x >> 8);
}
static inline uint32_t swap32(uint32_t __x)
{
return (__x >> 24) | (__x >> 8 & 0xff00) | (__x << 8 & 0xff0000) | (__x << 24);
}
static inline uint64_t swap64(uint64_t __x)
{
return ((swap32((uint32_t)__x) + 0ULL) << 32) | (swap32(__x >> 32));
}
static inline void toLeEndian(void* buf, int size)
{
#if ENDIANNESS_LE
return;
#else // ENDIANNESS_LE
switch (size) {
case 1:
*((uint8_t*)buf) = swap8(*(uint8_t*)buf);
break;
case 2:
*((uint16_t*)buf) = swap16(*(uint16_t*)buf);
break;
case 4:
*((uint32_t*)buf) = swap32(*(uint32_t*)buf);
break;
case 8:
*((uint64_t*)buf) = swap64(*(uint64_t*)buf);
break;
}
#endif // ENDIANNESS_LE
}
template <class T>
static inline T toLeEndianByType(T value)
{
#if ENDIANNESS_LE
return value;
#else // ENDIANNESS_LE
toLeEndian(&value, sizeof(T));
return value;
#endif // ENDIANNESS_LE
}
} // namespace logmessage
} // namespace oceanbase
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
oblogmsg is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
#pragma once
#include <vector>
#include <string>
using namespace std;
namespace oceanbase {
namespace logmessage {
struct BinLogBuf;
class LogMsgBuf {
public:
LogMsgBuf();
~LogMsgBuf();
const char* getValueByOffset(size_t offset);
size_t appendString(const char* string, size_t size);
size_t appendString(const std::string& string);
size_t appendBuf(const char* data, size_t size);
size_t appendBuf(const std::string& string);
size_t appendBuf(const BinLogBuf* sa, size_t size);
size_t appendStringArray(std::vector<std::string*>& sa);
size_t appendStringArray(const char** sa, size_t size);
void setHead(size_t size);
void copyHead(const char* head, size_t size);
void froceSetHeadSize(size_t size);
const char* getString(size_t* size);
size_t appendDataArray(std::vector<long>& sa);
size_t appendDataArray(uint8_t* sa, size_t size);
private:
inline void checkBuf(size_t size, char*& pos, uint32_t*& s, char*& head);
private:
char* buf;
size_t bufSize;
size_t bufPos;
char* defaultBuf;
size_t avg_size;
};
} // namespace logmessage
} // namespace oceanbase
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
oblogmsg is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
#pragma once
#include <string>
namespace oceanbase {
namespace logmessage {
class IColMeta;
class ITableMeta;
class IDBMeta;
class IMetaDataCollections;
class ILogRecord;
class LogMsgFactory {
public:
static std::string DFT_ColMeta;
static std::string DFT_TableMeta;
static std::string DFT_DBMeta;
static std::string DFT_METAS;
static std::string DFT_LR;
public:
/**
* Create an empty ColMeta by a specific type
*
* @param type is the name of the specific colmeta, default is "ColMetaImpl"
* @return instantialized colmeta
*/
static IColMeta* createColMeta(const std::string& type = DFT_ColMeta);
/**
* Create a meaningful ColMeta by a specific type with given serialized
* data and size
*
* @param type is the name of the specific colmeta, default is "ColMetaImpl"
* @param ptr is the address of a consecutive memory in which the
* serialized colmeta is stored
* @param size is the length of the consecutive memory
* @return instantialized colmeta
*/
static IColMeta* createColMeta(const std::string& type, const char* ptr, size_t size);
/**
* Create an empty TableMeta by a specific type
*
* @param type is the name of the specific tablemeta, default is "TableMetaImpl"
* @return instantialized tablemeta
*/
static ITableMeta* createTableMeta(const std::string& type = DFT_TableMeta);
/**
* Create a meaningful TableMeta by a specific type with given serialized data
* and size
*
* @param type is the name of the specific tablemeta, default is
* "TableMetaImpl"
* @param ptr is the address of a consecutive memory in which the
* date of a serialized tablemeta is stored
* @param size is the length of the consecutive memory
* @return instantialized tablemeta
*/
static ITableMeta* createTableMeta(const std::string& type, const char* ptr, size_t size);
/**
* Create an empty DBMeta by a specific type
*
* @param type is the name of the specific dbmeta, default is "DBMetaImpl"
* @return instantialized dbmeta
*/
static IDBMeta* createDBMeta(const std::string& type = DFT_DBMeta);
/**
* Create a meaningful DBMeta by a specific type with given serialized
* data and size
*
* @param type is the name of the specific dbmeta, default is "DBMetaImpl"
* @param ptr is the address of a consecutive memory in which the
* serialized dbmeta is stored
* @param size is the length of the consecutive memory
* @return instantialized dbmeta
*/
static IDBMeta* createDBMeta(const std::string& type, const char* ptr, size_t size);
/**
* Create an empty MetaDataCollections by a specific type
*
* @param type is the name of the specific metadatacollections,
* default is "MetaDataCollectionsImpl"
* @return instantialized metadatacollections
*/
static IMetaDataCollections* createMetaDataCollections(const std::string& type = DFT_METAS);
/**
* Create a meaningful MetaDataCollections by a specific type with given
* serialized data and size
*
* @param type is the name of the specific metadatacollections,
* default is "DBMetaImpl"
* @param ptr is the address of a consecutive memory in which the
* serialized metadatacollections is stored
* @param size is the length of the consecutive memory
* @param freeMem is to direct whether the assigned ptr should be
* freed after the metadatacollections is destroyed
* @return instantialized metadatacollections
*/
static IMetaDataCollections* createMetaDataCollections(
const std::string& type, const char* ptr, size_t size, bool freeMem);
/**
* Create a binlog record by the specific type with the judgement whether
* need initilizing non-serialized members in memory
*
* @param type is the name of the specific LogRecord,
* default is "LogRecordImpl"
* @param creating is to differentiate two kinds of usage, if creating is
* true, it means the created binlog record has not been
* serilized, all in-memory functions can be called. Otherwise
* if creating is false, only after-serialized function could
* be called
* @return the instantialized binlog record
*/
static ILogRecord* createLogRecord(const std::string& type = DFT_LR, bool creating = true);
/**
* Create a binlog record by the specific type from data stored in the
* consecutive memory directed by ptr with length size
*
* @param type is the name of the specific LogRecord,
* default is "LogRecordImpl"
* @param ptr is the address of the consecutive memory
* @param size is the length of the memory
* @return the instantialized binlog record
*/
static ILogRecord* createLogRecord(const std::string& type, const char* ptr, size_t size);
/**
* Destroy the binlog record created by the factory with the memory
* allocated by users with putOld and putNew
*
* @param record is the created record which is freed hereby
*/
static void destroy(ILogRecord*& record);
/**
* Destroy the binlog record created by the factory, the users memory
* is not freed
*
* @param record is the created record which is freed hereby
*/
static void destroyWithUserMemory(ILogRecord*& record);
/**
* Destroy the column meta created by the factory
*
* @param colMeta is the meta of the column to be freed
*/
static void destroy(IColMeta*& colMeta);
/**
* Destroy the table meta created by the factory
*
* @param tableMeta is the meta of the table to be freed
*/
static void destroy(ITableMeta*& tableMeta);
/**
* Destroy the database meta created by the factory
*
* @param dbMeta is the meta of the database to be freed
*/
static void destroy(IDBMeta*& dbMeta);
/**
* Destroy the collections of all db meta created by the factory
*
* @param metaColls is the collections of all meta to be freed
*/
static void destroy(IMetaDataCollections*& metaColls);
};
} // namespace logmessage
} // namespace oceanbase
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
oblogmsg is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
#pragma once
#include <string>
#include <vector>
#include <cstdint>
#include "UserData.h"
#include "BinLogBuf.h"
#include "LogMsgBuf.h"
namespace oceanbase {
namespace logmessage {
class StrArray;
struct LogRecInfo;
extern bool LOGREC_CRC;
extern bool LOGREC_PARSE_CRC;
#define BR_FAKE_DDL_COLNAME "ddl"
typedef enum RecordType {
EINSERT = 0,
EUPDATE,
EDELETE,
EREPLACE,
HEARTBEAT,
CONSISTENCY_TEST,
EBEGIN,
ECOMMIT,
EDDL,
EROLLBACK,
EDML,
INDEX_INSERT = 128,
INDEX_UPDATE,
INDEX_DELETE,
INDEX_REPLACE,
EUNKNOWN = 255,
} RECORD_TYPE;
enum FORMATERR {
FORMATOK = 0,
BUFOVERFLOW,
TYPENOTSUPPORT,
UNKNOWNTYPE,
UNKNOWNOPTYPE,
NULLTBLMETA,
NULLCOLMETA,
ENUMSETNULL
};
enum SOURCE_TYPE {
SRC_MYSQL = 0x00, // MySQL
SRC_OCEANBASE = 0x01, // Oceanbase
SRC_HBASE = 0X02, // HBase
SRC_ORACLE = 0x03, // Oracle
SRC_OCEANBASE_1_0 = 0x04, // Oceanbase V1
SRC_DB2 = 0x05, // DB2
SRC_UNKNOWN = 0x06
};
enum SOURCE_CATEGORY {
SRC_FULL_RECORDED = 0, // can get all column value from redo log
SRC_FULL_RETRIEVED, // can get part column value from redo log,other need fetch
SRC_FULL_FAKED,
SRC_PART_RECORDED,
SRC_NO
};
class ITableMeta;
class IDBMeta;
class IMetaDataCollections;
class ILogRecord : public UserDataInterface {
public:
virtual ~ILogRecord()
{}
public:
/* setter and getter */
// must set: record src type
virtual void setSrcType(int type) = 0;
virtual int getSrcType() const = 0;
// must set
virtual void setSrcCategory(int category) = 0;
virtual int getSrcCategory() const = 0;
virtual void setThreadId(uint32_t threadId) = 0;
virtual uint32_t getThreadId() = 0;
// must set: record's create time
virtual void setTimestamp(long timestamp) = 0;
virtual time_t getTimestamp() = 0;
// must set: record's type,like insert/delete/update/replace/heartbeat...
virtual int setRecordType(int aType) = 0;
virtual int recordType() = 0;
// must set: ITableMeta's encoding
virtual const char* recordEncoding() = 0;
// must set: database name
virtual void setDbname(const char* db) = 0;
virtual const char* dbname() const = 0;
// must set: table name
virtual void setTbname(const char* table) = 0;
virtual const char* tbname() const = 0;
// musst set when creating mode, parse mode no need: table's meta info
virtual void setTableMeta(ITableMeta* tblMeta) = 0;
virtual int getTableMeta(ITableMeta*& tblMeta) = 0;
// return table meta directly
virtual ITableMeta* getTableMeta() = 0;
// is record parsed from serialized data
virtual bool isParsedRecord() = 0;
virtual void setDBMeta(IDBMeta* dbMeta) = 0;
virtual IDBMeta* getDBMeta() = 0;
virtual void setExpiredTableMeta(ITableMeta* tblMeta) = 0;
virtual std::vector<ITableMeta*>& getExpiredTableMeta() = 0;
virtual void setExpiredDBMeta(IDBMeta* dbMeta) = 0;
virtual std::vector<IDBMeta*>& getExpiredDBMeta() = 0;
virtual void setExpiredMetaDataCollections(IMetaDataCollections* imc) = 0;
virtual IMetaDataCollections* getExpiredMetaDataCollections() = 0;
// muset set: set checkpoint,return like %d@%d
virtual void setCheckpoint(uint64_t file, uint64_t offset) = 0;
virtual const char* getCheckpoint() = 0;
/**
* ob: getCheckpoint1 High 32 bit checkpoint, getCheckpoint2 Low 32 bit checkpoint
*/
virtual uint64_t getCheckpoint1() = 0;
virtual uint64_t getCheckpoint2() = 0;
virtual uint64_t getFileNameOffset() = 0;
virtual uint64_t getFileOffset() = 0;
virtual void setFirstInLogevent(bool b) = 0;
virtual bool firstInLogevent() = 0;
virtual void setId(uint64_t id) = 0;
virtual uint64_t id() = 0;
virtual void setInstance(const char* instance) = 0;
virtual const char* instance() const = 0;
// this value will save at pkValue
virtual void setExtraInfo(const char* info) = 0;
virtual StrArray* extraInfo() const = 0;
virtual bool isTimemarked() const = 0;
virtual void setTimemarked(bool marked) = 0;
virtual void addTimemark(long time) = 0;
virtual std::vector<long>& getTimemark() = 0;
virtual std::vector<long>& getTimemark(size_t& length) = 0;
virtual void curveTimemark() = 0;
public:
/* column data */
/**
* 1. insert no old value,only has new value
* 2. delete no new value,only has old value
* 3. update/replace has new and old value
* 4. column must sort by ITableMeta's column
*/
virtual int putOld(std::string* val) = 0;
virtual int putNew(std::string* val) = 0;
virtual int putOld(const char* pos, int len) = 0;
virtual int putNew(const char* pos, int len) = 0;
virtual void setNewColumn(BinLogBuf* buf, int size) = 0;
virtual void setOldColumn(BinLogBuf* buf, int size) = 0;
virtual int getColumnCount() = 0;
virtual int putFilterRuleVal(const char* pos, int len) = 0;
virtual int16_t getRecordHash(
int16_t (*hashFunc)(const char** valueList, const size_t* valueSizeList, int count)) = 0;
virtual bool hashColumnSetted() = 0;
virtual void setHashFuncId(int id) = 0;
virtual int getHashFuncId() = 0;
virtual int setHashCol(std::vector<std::string>& hashColumns) = 0;
virtual void setHashColByPK() = 0;
virtual void clearOld() = 0;
virtual void clearNew() = 0;
// get all old value
virtual const std::vector<std::string*>& oldCols() = 0;
virtual BinLogBuf* oldCols(unsigned int& count) = 0;
virtual StrArray* parsedOldCols() const = 0;
// get all new value
virtual const std::vector<std::string*>& newCols() = 0;
virtual BinLogBuf* newCols(unsigned int& count) = 0;
virtual StrArray* parsedNewCols() const = 0;
// get all column names
virtual StrArray* parsedColNames() const = 0;
virtual StrArray* parsedColEncodings() const = 0;
virtual StrArray* parsedFilterRuleValues() const = 0;
virtual const uint8_t* parsedColTypes() const = 0;
virtual const uint8_t* parsedColFlags() const = 0;
virtual const std::vector<int>& pkKeys() = 0;
virtual const std::vector<int>& ukKeys() = 0;
public:
/* tostring and parse */
virtual int parse(const void* ptr, size_t size) = 0;
virtual int parseFast(const void* ptr, size_t size) = 0;
/**
* @return true success; false fail
*/
virtual bool parsedOK() = 0;
virtual size_t getRealSize() = 0;
/**
* serialize
* @return serialized ptr
*/
virtual const char* toString(size_t* size, LogMsgBuf* lmb = NULL, bool reserveMemory = false) = 0;
/**
* @return serialized ptr
*/
virtual const char* getFormatedString(size_t* size) = 0;
/**
* clear all to reuse, no free memory
*/
virtual void clear() = 0;
/**
* clear all,include memory
*/
virtual void clearWithUserMemory() = 0;
virtual void clearExpiredMeta() = 0;
virtual void setRecordEncoding(const char* encoding) = 0;
virtual void setSqlNo(int32_t sql_no) = 0;
virtual int32_t sqlNo() = 0;
virtual void setObTraceInfo(const char* ob_trace_info) = 0;
virtual const char* obTraceInfo() = 0;
// must set: record's create us
virtual void setRecordUsec(uint32_t usec) = 0;
virtual uint32_t getRecordUsec() = 0;
// get serialized string of record directly
virtual const char* getSerializedString(size_t* size) = 0;
};
class LogRecordImpl : public ILogRecord {
public:
LogRecordImpl(time_t timestamp, ITableMeta* tblMeta);
LogRecordImpl(const void* ptr, size_t size);
LogRecordImpl(bool creating = true, bool useLMB = false);
virtual ~LogRecordImpl();
public:
/* setter and getter */
virtual void setSrcType(int type);
virtual int getSrcType() const;
virtual void setSrcCategory(int category);
virtual int getSrcCategory() const;
virtual void setTimestamp(long timestamp);
virtual time_t getTimestamp();
virtual int setRecordType(int aType);
virtual int recordType();
virtual const char* recordEncoding();
virtual void setDbname(const char* db);
virtual const char* dbname() const;
virtual void setTbname(const char* table);
virtual const char* tbname() const;
virtual void setTableMeta(ITableMeta* tblMeta);
// if record is parsed from serialized data, tblMeta can not be null
// and will be set values parsed from serialized data.
// if tblMeta is Null pointer, will set current table meta to tblMeta
virtual int getTableMeta(ITableMeta*& tblMeta);
// return table meta directly
virtual ITableMeta* getTableMeta();
// is record parsed from serialized data
virtual bool isParsedRecord();
virtual void setDBMeta(IDBMeta* dbMeta);
virtual IDBMeta* getDBMeta();
virtual void setExpiredTableMeta(ITableMeta* tblMeta);
virtual std::vector<ITableMeta*>& getExpiredTableMeta();
virtual void setExpiredDBMeta(IDBMeta* dbMeta);
virtual std::vector<IDBMeta*>& getExpiredDBMeta();
virtual void setExpiredMetaDataCollections(IMetaDataCollections* imc);
virtual IMetaDataCollections* getExpiredMetaDataCollections();
virtual void setCheckpoint(uint64_t file, uint64_t offset);
virtual const char* getCheckpoint();
virtual uint64_t getCheckpoint1();
virtual uint64_t getCheckpoint2();
virtual uint64_t getFileNameOffset();
virtual uint64_t getFileOffset();
virtual void setFirstInLogevent(bool b);
virtual bool firstInLogevent();
virtual void setRecordUsec(uint32_t usec);
virtual uint32_t getRecordUsec();
virtual void setId(uint64_t id);
virtual uint64_t id();
virtual void setInstance(const char* instance);
virtual const char* instance() const;
virtual void setExtraInfo(const char* info);
virtual StrArray* extraInfo() const;
bool isTimemarked() const;
void setTimemarked(bool marked);
void addTimemark(long time);
std::vector<long>& getTimemark();
std::vector<long>& getTimemark(size_t& length);
virtual void curveTimemark();
virtual void setThreadId(uint32_t threadId);
virtual uint32_t getThreadId();
public:
/* column data */
virtual int putOld(std::string* val);
virtual int putNew(std::string* val);
virtual int putOld(const char* pos, int len);
virtual int putNew(const char* pos, int len);
virtual void setNewColumn(BinLogBuf* buf, int size);
virtual void setOldColumn(BinLogBuf* buf, int size);
virtual int getColumnCount();
virtual int putFilterRuleVal(const char* pos, int len);
virtual void clearOld();
virtual void clearNew();
virtual const std::vector<std::string*>& oldCols();
virtual BinLogBuf* oldCols(unsigned int& count);
virtual StrArray* parsedOldCols() const;
virtual const std::vector<std::string*>& newCols();
virtual BinLogBuf* newCols(unsigned int& count);
virtual const BinLogBuf* filterValues(unsigned int& count);
virtual StrArray* parsedNewCols() const;
virtual StrArray* parsedFilterRuleValues() const;
virtual StrArray* parsedColNames() const;
virtual StrArray* parsedColEncodings() const;
virtual const uint8_t* parsedColTypes() const;
virtual const uint8_t* parsedColFlags() const;
virtual const std::vector<int>& pkKeys();
virtual const std::vector<int>& ukKeys();
void elementAtPk(int off, char*& v, size_t& size) const;
void elementAtNew(int off, char*& v, size_t& size) const;
void elementAtOld(int off, char*& v, size_t& size) const;
const char* parseColumnValue(const char* columnName, size_t* size, int* columnType);
const char* parseColumnValue(const char* columnName, size_t* size, int* columnType, bool isPre);
public:
/* tostring and parse */
virtual int parse(const void* ptr, size_t size);
virtual int parseFast(const void* ptr, size_t size);
virtual bool parsedOK();
virtual size_t getRealSize();
virtual const char* toString(size_t* size, LogMsgBuf* lmb = NULL, bool reserveMemory = false);
virtual const char* getFormatedString(size_t* size);
virtual void clear();
virtual void clearWithUserMemory();
virtual void clearExpiredMeta();
virtual bool hashColumnSetted();
virtual int16_t getRecordHash(int16_t (*hashFunc)(const char** valueList, const size_t* valueSizeList, int count));
virtual void setHashFuncId(int id);
virtual int getHashFuncId();
virtual int setHashCol(std::vector<std::string>& hashColumns);
virtual void setHashColByPK();
virtual void getPKStringArrayData(const char*& v, size_t& size);
public:
virtual void setUserData(void* data);
virtual void* getUserData();
virtual void setRecordEncoding(const char* encoding);
virtual void setSqlNo(int32_t sql_no);
virtual int32_t sqlNo();
virtual void setObTraceInfo(const char* ob_trace_info);
virtual const char* obTraceInfo();
virtual const char* getSerializedString(size_t* size);
protected:
LogRecInfo* m_lr;
std::string m_buf;
bool m_timemarked;
void* m_userData;
};
} // namespace logmessage
} // namespace oceanbase
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
oblogmsg is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
#pragma once
#include <cstdio>
#include <ctime>
#include <pthread.h>
#include <vector>
#include <string>
#include "UserData.h"
namespace oceanbase {
namespace logmessage {
class StrArray;
enum logmsg_field_types {
LOGMSG_TYPE_DECIMAL,
LOGMSG_TYPE_TINY,
LOGMSG_TYPE_SHORT,
LOGMSG_TYPE_LONG,
LOGMSG_TYPE_FLOAT,
LOGMSG_TYPE_DOUBLE,
LOGMSG_TYPE_NULL,
LOGMSG_TYPE_TIMESTAMP,
LOGMSG_TYPE_LONGLONG,
LOGMSG_TYPE_INT24,
LOGMSG_TYPE_DATE,
LOGMSG_TYPE_TIME,
LOGMSG_TYPE_DATETIME,
LOGMSG_TYPE_YEAR,
LOGMSG_TYPE_NEWDATE,
LOGMSG_TYPE_VARCHAR,
LOGMSG_TYPE_BIT,
LOGMSG_TYPE_NEWDECIMAL = 246,
LOGMSG_TYPE_ENUM = 247,
LOGMSG_TYPE_SET = 248,
LOGMSG_TYPE_TINY_BLOB = 249,
LOGMSG_TYPE_MEDIUM_BLOB = 250,
LOGMSG_TYPE_LONG_BLOB = 251,
LOGMSG_TYPE_BLOB = 252,
LOGMSG_TYPE_VAR_STRING = 253,
LOGMSG_TYPE_STRING = 254,
LOGMSG_TYPE_GEOMETRY = 255,
LOGMSG_TYPES
};
// column's meta
struct ColMetaInfo;
class IDBMeta;
class IMetaDataCollections;
struct _trie_tree;
class IColMeta : public UserDataInterface {
public:
IColMeta();
IColMeta(const void* ptr, size_t size);
virtual ~IColMeta();
public:
// override
virtual const char* getName();
virtual int getType();
virtual long getLength();
virtual const char* getOriginType();
virtual long getPrecision();
virtual long getScale();
virtual bool isSigned();
virtual bool isPK();
virtual bool isRuleCol();
virtual bool isUK();
virtual bool isNotNull();
virtual int getDecimals();
virtual const char* getDefault();
virtual const char* getEncoding();
virtual int getRequired();
virtual StrArray* getValuesOfEnumSet();
virtual bool isGenerated();
virtual void setFlag(unsigned char flag);
virtual unsigned char getFlag();
virtual void setName(const char* name);
virtual void setType(int type);
virtual void setLength(long length);
virtual void setOriginType(const char* origin);
virtual void setPrecision(long precision);
virtual void setScale(long scale);
virtual void setSigned(bool b);
virtual void setIsPK(bool b);
virtual void setIsRuleCol(bool b);
virtual void setIsUK(bool b);
virtual void setNotNull(bool b);
virtual void setDecimals(int decimals);
virtual void setDefault(const char* def);
virtual void setDefault(const char* def, size_t length);
virtual void setEncoding(const char* enc);
virtual void setRequired(int required);
virtual void setValuesOfEnumSet(std::vector<std::string>& v);
virtual void setValuesOfEnumSet(std::vector<const char*>& v);
virtual void setValuesOfEnumSet(const char** v, size_t size);
virtual void setGenerated(bool Generated);
virtual void setHiddenRowKey();
virtual bool isHiddenRowKey();
public:
int appendTo(std::string& s);
size_t getRealSize();
int parse(const void* ptr, size_t size);
bool parsedOK();
public:
virtual void setUserData(void* data);
virtual void* getUserData();
private:
ColMetaInfo* m_col;
void* m_userData;
};
// table's meta
struct TableMetaInfo;
class ITableMeta : public UserDataInterface {
public:
ITableMeta();
ITableMeta(const void* ptr, size_t size);
virtual ~ITableMeta();
public:
// override
virtual const char* getName();
virtual bool hasPK();
virtual bool hasUK();
virtual const char* getPKs();
virtual const char* getUKs();
virtual const int* getPKs(int& size) const;
virtual const int* getUKs(int& size) const;
virtual const char* getEncoding();
virtual IDBMeta* getDBMeta();
virtual void setName(const char* name);
virtual void setHasPK(bool b);
virtual void setPKIndice(const std::vector<int>& indice);
virtual void setPKs(const char* pks);
virtual void setHasUK(bool b);
virtual void setUKs(const char* uks);
virtual void setEncoding(const char* enc);
virtual void setDBMeta(IDBMeta* dbMeta);
virtual void setPkinfo(const char* info);
virtual const char* getPkinfo();
virtual void setUkinfo(const char* info);
virtual const char* getUkinfo();
bool hashColumnSetted();
const int* getHashColumnIdx(int& hashCoumnCount, char**& hashValueList, size_t*& hashValueSizeList);
void setHashColByPK();
int setHashCol(std::vector<std::string>& hashColumns);
void setHashFuncId(int id);
int getHashFuncId();
void trySerializeMetaDataAsMsgArea(std::vector<const char*>& extra_infos);
const std::string& getNameData();
const std::string& getEncodingData();
const std::string& getcolTypeData();
const std::string& getPkData();
const std::string& getUkData();
const std::string& getkeyData();
const std::string& getColumnFlagData();
const std::string& getNotNullData();
const std::string& getSignedData();
const std::string& getDecimalsData();
const std::string& getDefaultData();
const std::string& getColLengthData();
const std::string& getOriginTypeData();
const std::string& getColPrecisionData();
const std::string& getColScaleData();
public:
/**
* get all column name
*/
std::vector<std::string>& getColNames();
/**
* get PK column name
*/
std::vector<std::string>& getPKColNames();
std::vector<std::string>& getUKColNames();
/**
* get column's meta by name
*/
virtual IColMeta* getCol(const char* colName);
virtual int getColIndex(const char* colName);
/**
* get Column count
*/
virtual int getColCount();
/*
* get column's meta by column id
*/
virtual IColMeta* getCol(int index);
virtual int getColNum(const char* colName);
/**
* append a column meta
*/
virtual int append(const char* colName, IColMeta* colMeta);
/* For partial */
virtual bool isDropped();
virtual void setDropped(bool value);
virtual const char* getNewName();
virtual void setNewName(const char* name);
public:
int appendTo(std::string& s);
size_t getRealSize();
int parse(const void* ptr, size_t size);
bool parsedOK();
/*
* parse key index like (2, 0, 1) or (0, 1, 2)
* return index vector, if format is invalid,
* return -1, if success, return 0.
*/
int parseKeyIndex(std::string indexStr, std::vector<int>& indice);
/*
* get pk or uk keys from pkinfo or ukinfo like (0, 1, 2......)
*/
int getKeysFromInfo(std::string info, std::string& keys, StrArray* colNames);
public:
virtual void setUserData(void* data);
virtual void* getUserData();
virtual void** getUserDataPtr();
private:
TableMetaInfo* m_tbl;
void* m_userData;
std::string m_colNameData;
std::string m_encodingData;
std::string m_colTypeData;
std::string m_PkData;
std::string m_UkData;
std::string m_keyData;
std::string m_columnFlagData;
std::string m_colNotNullData;
std::string m_colSignedData;
std::string m_colDecimalsData;
std::string m_colDefaultData;
std::string m_colLengthData;
std::string m_colOriginTypeData;
std::string m_colPrecisionData;
std::string m_colScaleData;
pthread_mutex_t m_mdMutex;
bool m_DataOk;
int* m_hashColumnIdx;
int m_hashColumnSize;
bool m_hashColumnSetted;
int m_hashFuncId;
char** m_hashColumValueList;
size_t* m_hashColumValueSizeList;
};
// DB's meta
struct DBMetaInfo;
class IDBMeta : public UserDataInterface {
public:
IDBMeta();
IDBMeta(const void* ptr, size_t size);
virtual ~IDBMeta();
public:
// override
virtual const char* getName();
virtual const char* getEncoding();
virtual IMetaDataCollections* getMetaDataCollections();
virtual void setName(const char* name);
virtual void setEncoding(const char* enc);
virtual void setMetaDataCollections(IMetaDataCollections* mdc);
virtual int getTblCount();
/**
* get table's meta by name
*/
virtual ITableMeta* get(const char* tblName);
virtual ITableMeta* get(int index);
/**
* add a table's meta
*/
virtual int put(ITableMeta* tblMeta);
/* For partial */
virtual bool isDropped();
virtual void setDropped(bool value);
public:
virtual int eraseMapIterator();
virtual int getFromMapIterator(const char** tblName, ITableMeta** tblMeta);
virtual int nextMapIterator(bool erase);
virtual int resetMapIterator();
virtual int erase(const char* tableName, bool delayDeleteMeta);
virtual int appendTo(std::string& s);
virtual size_t getRealSize();
virtual int parse(const void* ptr, size_t size);
virtual bool parsedOK();
public:
virtual void setUserData(void* data);
virtual void* getUserData();
virtual void** getUserDataPtr();
private:
DBMetaInfo* m_db;
void* m_userData;
};
// all db's meta
struct MetaDataCollectionInfo;
class IMetaDataCollections : public UserDataInterface {
public:
IMetaDataCollections();
IMetaDataCollections(
const void* ptr, size_t size, bool removePtr = false); // removePtr means if free ptr when destroy object
virtual ~IMetaDataCollections();
public:
// override
virtual unsigned getMetaVerNum();
virtual IMetaDataCollections* getPrev();
virtual time_t getTimestamp();
virtual void setMetaVerNum(unsigned metaVerNum);
virtual void setPrev(IMetaDataCollections* prev);
virtual void setTimestamp(time_t timestamp);
/**
* get Db count
*/
virtual int getDbCount();
/**
* get Db meta by name
*/
virtual IDBMeta* get(const char* dbname);
/**
* get Db meta by id
*/
virtual IDBMeta* get(int index);
/**
* get table meta by dbname and tablename
*/
virtual ITableMeta* get(const char* dbName, const char* tblName);
/**
* add a db meta
*/
virtual int put(IDBMeta* dbMeta);
/**
* serialize to string
*/
virtual int toString(std::string& s);
/**
* parse from readonly ptr
*/
virtual int parse(const void* ptr, size_t size);
/**
* if parsed success
*/
virtual bool parsedOK();
virtual size_t getRealSize();
virtual int eraseMapIterator();
virtual int getFromMapIterator(const char** dbName, IDBMeta** dbMeta);
virtual int nextMapIterator(bool erase);
virtual int resetMapIterator();
virtual int erase()
{
return 0;
}
virtual int erase(const char* dbName, bool delayDeleteMeta);
virtual int erase(const char* dbName, const char* tbName, bool delayDeleteMeta);
public:
virtual void setUserData(void* data);
virtual void* getUserData();
private:
MetaDataCollectionInfo* m_coll;
void* m_userData;
};
} // namespace logmessage
} // namespace oceanbase
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
oblogmsg is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
#pragma once
#include <cstdint>
namespace oceanbase {
namespace logmessage {
enum { MT_UNKNOWN = 0, MT_META, MT_FIXED, MT_VAR, MT_EXT };
struct MsgHeader {
uint16_t m_msgType;
uint16_t m_version;
uint32_t m_size;
};
} // namespace logmessage
} // namespace oceanbase
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
oblogmsg is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
#pragma once
#include <cstdint>
namespace oceanbase {
namespace logmessage {
enum {
DT_UNKNOWN = 0x0000,
DT_INT8 = 0x0001,
DT_UINT8 = 0x0002,
DT_INT16 = 0x0003,
DT_UINT16 = 0x0004,
DT_INT32 = 0x0005,
DT_UINT32 = 0x0006,
DT_INT64 = 0x0007,
DT_UINT64 = 0x0008,
DT_FLOAT = 0x0009,
DT_DOUBLE = 0x000a,
DT_STRING = 0x000b,
TOTAL_DT,
DT_MASK = 0x000F,
DC_ARRAY = 0x0010,
DC_NULL = 0x0020,
DC_MASK = 0x0030,
};
const char STUFF_CHAR = '\0';
typedef uint8_t DT_TYPE;
typedef uint32_t STRLEN_TYPE;
typedef uint32_t COUNT_TYPE;
typedef uint32_t OFFSET_TYPE;
class MsgType {
public:
static int getValType(const char* typeName);
};
} // namespace logmessage
} // namespace oceanbase
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
oblogmsg is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
#pragma once
#include <sys/types.h>
namespace oceanbase {
namespace logmessage {
class StrArray {
protected:
StrArray() = default;
public:
virtual ~StrArray() = default;
virtual size_t size() = 0;
virtual int elementAt(int i, const char*& s, size_t& length) = 0;
virtual const char* operator[](int i) = 0;
};
} // namespace logmessage
} // namespace oceanbase
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
oblogmsg is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
#pragma once
namespace oceanbase {
namespace logmessage {
class UserDataInterface {
public:
virtual ~UserDataInterface()
{}
virtual void setUserData(void* data) = 0;
virtual void* getUserData() = 0;
};
} // namespace logmessage
} // namespace oceanbase
Name: devdeps-oblogmsg
Version: %(echo $VERSION)
Release: %(echo $RELEASE)%{?dist}
# if you want use the parameter of rpm_create on build time,
# uncomment below
Summary: oblogmsg
Group: Development/Tools
License: Commercial
Url: oceanbase.com
%define _prefix /usr/local/oceanbase/deps/devel
%define __strip /bin/true
%define __os_install_post %{nil}
%define debug_package %{nil}
# uncomment below, if your building depend on other packages
#BuildRequires: package_name = 1.0.0
# uncomment below, if depend on other packages
#Requires: package_name = 1.0.0
%description
# if you want publish current svn URL or Revision use these macros
Lua static library for oceanbase
#%debug_package
# support debuginfo package, to reduce runtime package size
# prepare your files
%install
mkdir -p $RPM_BUILD_ROOT/%{_prefix}
mkdir -p $RPM_BUILD_ROOT/%{_prefix}/include/oblogmsg
mkdir -p $RPM_BUILD_ROOT/%{_prefix}/lib
cd $OLDPWD/../
sh build.sh --init release
cd build_release
make -j8
cd ..
cp build_release/src/liboblogmsg.a $RPM_BUILD_ROOT/%{_prefix}/lib/
cp build_release/src/liboblogmsg.so $RPM_BUILD_ROOT/%{_prefix}/lib/
cp include/*.h $RPM_BUILD_ROOT/%{_prefix}/include/oblogmsg/
# package infomation
%files
# set file attribute here
%defattr(-,root,root)
# need not list every file here, keep it as this
%{_prefix}
## create an empy dir
# %dir %{_prefix}/var/log
## need bakup old config file, so indicate here
# %config %{_prefix}/etc/sample.conf
## or need keep old config file, so indicate with "noreplace"
# %config(noreplace) %{_prefix}/etc/sample.conf
## indicate the dir for crontab
# %attr(644,root,root) %{_crondir}/*
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%changelog
* Tue Sep 6 2022 wenxignsen.wxs
- for ob 4.0 opensource
(base)
set(SRC_LIST LogMsgBuf.cpp
LogMsgFactory.cpp
LogRecord.cpp
MetaInfo.cpp
MsgType.cpp
MsgVarArea.cpp
Crc32.cpp
)
add_library(oblogmsg_shared SHARED ${SRC_LIST})
add_library(oblogmsg_static STATIC ${SRC_LIST})
foreach(T IN ITEMS oblogmsg_shared oblogmsg_static)
target_compile_features(${T} PUBLIC cxx_std_11)
target_compile_options(${T} PRIVATE -Wno-invalid-offsetof)
set_target_properties(${T} PROPERTIES OUTPUT_NAME oblogmsg
CXX_STANDARD 11
CXX_EXTENSIONS OFF
POSITION_INDEPENDENT_CODE ON)
target_include_directories(${T} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>)
endforeach()
# ensure that the build results can be run on systems with lower libstdc++ version than the build system
target_link_libraries(oblogmsg_shared PRIVATE -static-libstdc++)
# with namespace oceanbase
add_library(oceanbase::oblogmsg_shared ALIAS oblogmsg_shared)
add_library(oceanbase::oblogmsg_static ALIAS oblogmsg_static)
此差异已折叠。
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
oblogmsg is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
// g++ -o Crc32 Crc32.cpp -O3 -lrt -march=native -mtune=native
// if running on an embedded system, you might consider shrinking the
// big Crc32Lookup table:
// - crc32_bitwise doesn't need it at all
// - crc32_halfbyte has its own small lookup table
// - crc32_1byte needs only Crc32Lookup[0]
// - crc32_4bytes needs only Crc32Lookup[0..3]
// - crc32_8bytes needs only Crc32Lookup[0..7]
// - crc32_4x8bytes needs only Crc32Lookup[0..7]
// - crc32_16bytes needs all of Crc32Lookup
uint32_t crc32_halfbyte(const void* data, size_t length, uint32_t previousCrc32 = 0);
uint32_t crc32_1byte(const void* data, size_t length, uint32_t previousCrc32 = 0);
uint32_t crc32_4bytes(const void* data, size_t length, uint32_t previousCrc32 = 0);
uint32_t crc32_8bytes(const void* data, size_t length, uint32_t previousCrc32 = 0);
uint32_t crc32_4x8bytes(const void* data, size_t length, uint32_t previousCrc32 = 0);
uint32_t crc32_16bytes(const void* data, size_t length, uint32_t previousCrc32 = 0);
uint32_t crc32_16bytes_prefetch(
const void* data, size_t length, uint32_t previousCrc32 = 0, size_t prefetchAhead = 256);
#define crc32_fast crc32_16bytes
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
oblogmsg is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
#include <cstdint>
#include <cstring>
#include "MsgType.h"
#include "LogMsgBuf.h"
#include "BinLogBuf.h"
#include "MsgHeader.h"
#include "Endian.h"
namespace oceanbase {
namespace logmessage {
#define LogMsgHeadSize (sizeof(MsgHeader) + sizeof(COUNT_TYPE))
#define DefaultLogMsgBufSize 1024 * 1024 * 32
#define LOG_MSG_MAX_TAIL_SIZE 1024
inline void LogMsgBuf::checkBuf(size_t size, char*& pos, STRLEN_TYPE*& s, char*& head)
{
if (bufSize < size + (pos - buf) + LOG_MSG_MAX_TAIL_SIZE) {
char* tmp = new char[bufSize = (pos - buf) + 2 * (size) + LOG_MSG_MAX_TAIL_SIZE];
memcpy(tmp, buf, pos - buf);
pos = tmp + (pos - buf);
s = (STRLEN_TYPE*)(tmp + ((char*)s - buf));
head = tmp + ((char*)(head)-buf);
if (buf != defaultBuf)
delete[] buf;
buf = tmp;
}
}
LogMsgBuf::LogMsgBuf()
{
buf = new char[bufSize = DefaultLogMsgBufSize];
defaultBuf = buf;
bufPos = 0;
avg_size = 0;
}
LogMsgBuf::~LogMsgBuf()
{
if (buf != NULL)
delete[] buf;
if (defaultBuf != buf && defaultBuf !=NULL)
delete[] defaultBuf;
buf = NULL;
defaultBuf = NULL;
bufPos = 0;
}
const char* LogMsgBuf::getValueByOffset(size_t offset)
{
return buf + offset + LogMsgHeadSize + sizeof(DT_TYPE) + sizeof(COUNT_TYPE);
}
size_t LogMsgBuf::appendString(const char* string, size_t size)
{
size_t offset = bufPos - LogMsgHeadSize;
*(DT_TYPE*)(buf + bufPos) = (DT_TYPE)(DT_STRING);
if (string == NULL) {
(*(DT_TYPE*)(buf + bufPos)) |= DC_NULL;
return (bufPos += sizeof(DT_TYPE));
}
*(STRLEN_TYPE*)(buf + bufPos + sizeof(DT_TYPE)) = size + 1;
toLeEndian(buf + bufPos + sizeof(DT_TYPE), sizeof(STRLEN_TYPE));
memcpy(buf + bufPos + sizeof(DT_TYPE) + sizeof(STRLEN_TYPE), string, size);
bufPos += (sizeof(DT_TYPE) + sizeof(STRLEN_TYPE) + size) + 1;
buf[bufPos - 1] = 0;
return offset;
}
size_t LogMsgBuf::appendString(const std::string& string)
{
size_t offset = bufPos - LogMsgHeadSize, size = string.size();
*(DT_TYPE*)(buf + bufPos) = (DT_TYPE)(DT_STRING);
if (size == 0) {
(*(DT_TYPE*)(buf + bufPos)) |= DC_NULL;
return (bufPos += sizeof(DT_TYPE));
}
*(STRLEN_TYPE*)(buf + bufPos + sizeof(DT_TYPE)) = size + 1;
toLeEndian(buf + bufPos + sizeof(DT_TYPE), sizeof(STRLEN_TYPE));
strncpy(buf + bufPos + sizeof(DT_TYPE) + sizeof(STRLEN_TYPE), string.c_str(), size + 1);
bufPos += (sizeof(DT_TYPE) + sizeof(STRLEN_TYPE) + size + 1);
return offset;
}
size_t LogMsgBuf::appendBuf(const char* data, size_t size)
{
size_t offset = bufPos - LogMsgHeadSize;
memcpy(buf + bufPos, data, size);
bufPos += size;
return offset;
}
size_t LogMsgBuf::appendBuf(const std::string& string)
{
size_t offset = bufPos - LogMsgHeadSize;
memcpy(buf + bufPos, string.c_str(), string.size());
bufPos += string.size();
return offset;
}
size_t LogMsgBuf::appendBuf(const BinLogBuf* sa, size_t size)
{
size_t offset = bufPos - LogMsgHeadSize;
*(DT_TYPE*)(buf + bufPos) = (DT_TYPE)(DT_STRING | DC_ARRAY);
bufPos += sizeof(DT_TYPE);
if (sa == NULL || size == 0) {
*(COUNT_TYPE*)(buf + bufPos) = (COUNT_TYPE)(0);
toLeEndian(buf + bufPos, sizeof(COUNT_TYPE));
bufPos += sizeof(COUNT_TYPE);
return offset;
}
*(COUNT_TYPE*)(buf + bufPos) = (COUNT_TYPE)(size);
toLeEndian(buf + bufPos, sizeof(COUNT_TYPE));
bufPos += sizeof(COUNT_TYPE);
COUNT_TYPE i = 0;
char *pos = buf + bufPos, *head;
STRLEN_TYPE* s = (STRLEN_TYPE*)pos;
pos += sizeof(STRLEN_TYPE) * (size + 1);
head = pos;
for (i = 0; i < size; ++i) {
s[i] = pos - head;
toLeEndian(&(s[i]), sizeof(STRLEN_TYPE));
if (sa[i].buf != NULL) {
checkBuf(sa[i].buf_used_size, pos, s, head);
memcpy(pos, sa[i].buf, sa[i].buf_used_size);
pos[sa[i].buf_used_size] = 0;
pos += (sa[i].buf_used_size + 1);
}
}
s[i] = pos - head;
toLeEndian(&(s[i]), sizeof(STRLEN_TYPE));
bufPos = pos - buf;
return offset;
}
size_t LogMsgBuf::appendStringArray(std::vector<std::string*>& sa)
{
size_t offset = bufPos - LogMsgHeadSize, size = sa.size();
*(DT_TYPE*)(buf + bufPos) = (DT_TYPE)(DT_STRING | DC_ARRAY);
bufPos += sizeof(DT_TYPE);
*(COUNT_TYPE*)(buf + bufPos) = (COUNT_TYPE)(sa.size());
toLeEndian(buf + bufPos, sizeof(COUNT_TYPE));
if ((COUNT_TYPE)(sa.size()) == 0) {
bufPos += sizeof(COUNT_TYPE);
return offset;
}
bufPos += sizeof(COUNT_TYPE);
STRLEN_TYPE len;
COUNT_TYPE i = 0;
char *pos = buf + bufPos, *head;
STRLEN_TYPE* s = (STRLEN_TYPE*)pos;
pos += sizeof(STRLEN_TYPE) * (size + 1);
head = pos;
for (i = 0; i < size; ++i) {
s[i] = pos - head;
toLeEndian(&(s[i]), sizeof(STRLEN_TYPE));
if (sa[i] != NULL) {
len = sa[i]->size();
checkBuf(len, pos, s, head);
memcpy(pos, sa[i]->c_str(), len);
pos[len] = 0;
pos += (len + 1);
}
}
s[i] = pos - head;
toLeEndian(&(s[i]), sizeof(STRLEN_TYPE));
bufPos = pos - buf;
return offset;
}
size_t LogMsgBuf::appendStringArray(const char** sa, size_t size)
{
size_t offset = bufPos - LogMsgHeadSize;
*(DT_TYPE*)(buf + bufPos) = (DT_TYPE)(DT_STRING | DC_ARRAY);
bufPos += sizeof(DT_TYPE);
*(COUNT_TYPE*)(buf + bufPos) = (COUNT_TYPE)(size);
toLeEndian(buf + bufPos, sizeof(COUNT_TYPE));
if ((COUNT_TYPE)(size) == 0) {
bufPos += sizeof(COUNT_TYPE);
return offset;
}
bufPos += sizeof(COUNT_TYPE);
STRLEN_TYPE len;
COUNT_TYPE i = 0;
char *pos = buf + bufPos, *head;
STRLEN_TYPE* s = (STRLEN_TYPE*)pos;
pos += sizeof(STRLEN_TYPE) * (size + 1);
head = pos;
for (i = 0; i < size; ++i) {
s[i] = pos - head;
toLeEndian(&(s[i]), sizeof(STRLEN_TYPE));
if (sa[i] != NULL) {
len = strlen(sa[i]) + 1;
checkBuf(len, pos, s, head);
memcpy(pos, sa[i], len);
pos += len;
}
}
s[i] = pos - head;
toLeEndian(&(s[i]), sizeof(STRLEN_TYPE));
bufPos = pos - buf;
return offset;
}
size_t LogMsgBuf::appendDataArray(std::vector<long>& sa)
{
size_t offset = bufPos - LogMsgHeadSize;
*(DT_TYPE*)(buf + bufPos) = (DT_TYPE)(DT_INT64 | DC_ARRAY);
bufPos += sizeof(DT_TYPE);
*(COUNT_TYPE*)(buf + bufPos) = (COUNT_TYPE)(sa.size());
toLeEndian(buf + bufPos, sizeof(COUNT_TYPE));
if ((COUNT_TYPE)(sa.size()) == 0) {
bufPos += sizeof(COUNT_TYPE);
return offset;
}
bufPos += sizeof(COUNT_TYPE);
COUNT_TYPE i = 0, j = sa.size();
char* pos = buf + bufPos;
pos += sizeof(STRLEN_TYPE) * i;
for (i = 0; i < j; ++i) {
*(long*)pos = sa[i];
toLeEndian(pos, sizeof(long));
pos += sizeof(long);
}
bufPos = pos - buf;
return offset;
}
size_t LogMsgBuf::appendDataArray(uint8_t* sa, size_t size)
{
size_t offset = bufPos - LogMsgHeadSize;
*(DT_TYPE*)(buf + bufPos) = (DT_TYPE)(DT_UINT8 | DC_ARRAY);
bufPos += sizeof(DT_TYPE);
*(COUNT_TYPE*)(buf + bufPos) = (COUNT_TYPE)(size);
toLeEndian(buf + bufPos, sizeof(COUNT_TYPE));
if ((COUNT_TYPE)(size) == 0 || sa == NULL) {
bufPos += sizeof(COUNT_TYPE);
return offset;
}
bufPos += sizeof(COUNT_TYPE);
memcpy(buf + bufPos, sa, size);
bufPos += size;
return offset;
}
void LogMsgBuf::setHead(size_t size)
{
bufPos = size + LogMsgHeadSize + sizeof(DT_TYPE) + sizeof(COUNT_TYPE);
if (buf != defaultBuf) {
if (avg_size > DefaultLogMsgBufSize) {
if (avg_size < ((bufSize + DefaultLogMsgBufSize) >> 1)) {
delete[] buf;
buf = new char[bufSize = (bufSize + DefaultLogMsgBufSize) >> 1];
}
} else {
delete[] buf;
buf = defaultBuf;
bufSize = DefaultLogMsgBufSize;
}
}
}
void LogMsgBuf::copyHead(const char* head, size_t size)
{
((struct MsgHeader*)buf)->m_msgType = MT_VAR;
toLeEndian(&(((struct MsgHeader*)buf)->m_msgType), sizeof(uint16_t));
((struct MsgHeader*)buf)->m_version = 1;
toLeEndian(&(((struct MsgHeader*)buf)->m_version), sizeof(uint16_t));
((struct MsgHeader*)buf)->m_size = bufPos - (sizeof(struct MsgHeader));
toLeEndian(&(((struct MsgHeader*)buf)->m_size), sizeof(uint32_t));
*(COUNT_TYPE*)(buf + sizeof(struct MsgHeader)) = 0;
toLeEndian(buf + sizeof(struct MsgHeader), sizeof(COUNT_TYPE));
*(buf + LogMsgHeadSize) = (DT_TYPE)(DT_UINT8 | DC_ARRAY);
toLeEndian(buf + LogMsgHeadSize, sizeof(DT_TYPE));
*(COUNT_TYPE*)(buf + LogMsgHeadSize + sizeof(DT_TYPE)) = size;
toLeEndian(buf + LogMsgHeadSize + sizeof(DT_TYPE), sizeof(COUNT_TYPE));
memcpy(buf + LogMsgHeadSize + sizeof(DT_TYPE) + sizeof(COUNT_TYPE), head, size);
}
void LogMsgBuf::froceSetHeadSize(size_t size)
{
*(COUNT_TYPE*)(buf + LogMsgHeadSize + sizeof(DT_TYPE)) = size;
toLeEndian(buf + LogMsgHeadSize + sizeof(DT_TYPE), sizeof(COUNT_TYPE));
}
const char* LogMsgBuf::getString(size_t* size)
{
*size = bufPos;
if (buf != defaultBuf && bufPos > DefaultLogMsgBufSize)
avg_size = ((((long)avg_size >> 1) + (long)bufPos) >> 1) + (bufPos >> 2);
else
avg_size = (((long)avg_size + (long)bufPos) >> 1);
return buf;
}
} // namespace logmessage
} // namespace oceanbase
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
oblogmsg is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
#include "LogMsgFactory.h"
#include "MetaInfo.h"
#include "LogRecord.h"
using namespace std;
namespace oceanbase {
namespace logmessage {
string LogMsgFactory::DFT_ColMeta = "ColMetaImpl";
string LogMsgFactory::DFT_TableMeta = "TableMetaImpl";
string LogMsgFactory::DFT_DBMeta = "DBMetaImpl";
string LogMsgFactory::DFT_METAS = "MetaDataCollectionsImpl";
string LogMsgFactory::DFT_LR = "LogRecordImpl";
IColMeta* LogMsgFactory::createColMeta(const string& type)
{
if (type == DFT_ColMeta)
return new IColMeta();
else
return NULL;
}
IColMeta* LogMsgFactory::createColMeta(const string& type, const char* ptr, size_t size)
{
if (type == DFT_ColMeta)
return new IColMeta(ptr, size);
else
return NULL;
}
ITableMeta* LogMsgFactory::createTableMeta(const string& type)
{
if (type == DFT_TableMeta)
return new ITableMeta();
else
return NULL;
}
ITableMeta* LogMsgFactory::createTableMeta(const string& type, const char* ptr, size_t size)
{
if (type == DFT_TableMeta)
return new ITableMeta(ptr, size);
else
return NULL;
}
IDBMeta* LogMsgFactory::createDBMeta(const string& type)
{
if (type == DFT_DBMeta)
return new IDBMeta();
else
return NULL;
}
IDBMeta* LogMsgFactory::createDBMeta(const string& type, const char* ptr, size_t size)
{
if (type == DFT_DBMeta)
return new IDBMeta(ptr, size);
else
return NULL;
}
IMetaDataCollections* LogMsgFactory::createMetaDataCollections(const string& type)
{
if (type == DFT_METAS)
return new IMetaDataCollections();
return NULL;
}
IMetaDataCollections* LogMsgFactory::createMetaDataCollections(
const string& type, const char* ptr, size_t size, bool clearGarbage)
{
if (type == DFT_METAS)
return new IMetaDataCollections(ptr, size, clearGarbage);
return NULL;
}
ILogRecord* LogMsgFactory::createLogRecord(const std::string& type, bool creating)
{
if (type == DFT_LR)
return new LogRecordImpl(creating, true);
return NULL;
}
ILogRecord* LogMsgFactory::createLogRecord(const std::string& type, const char* ptr, size_t size)
{
if (type == DFT_LR)
return new LogRecordImpl(ptr, size);
return NULL;
}
void LogMsgFactory::destroy(ILogRecord*& record)
{
if (record) {
record->clear();
delete record;
record = NULL;
}
}
void LogMsgFactory::destroyWithUserMemory(ILogRecord*& record)
{
if (record) {
delete record;
record = NULL;
}
}
void LogMsgFactory::destroy(IColMeta*& colMeta)
{
if (colMeta) {
delete colMeta;
colMeta = NULL;
}
}
void LogMsgFactory::destroy(ITableMeta*& tableMeta)
{
if (tableMeta) {
delete tableMeta;
tableMeta = NULL;
}
}
void LogMsgFactory::destroy(IDBMeta*& dbMeta)
{
if (dbMeta) {
delete dbMeta;
dbMeta = NULL;
}
}
void LogMsgFactory::destroy(IMetaDataCollections*& metaColls)
{
if (metaColls) {
delete metaColls;
metaColls = NULL;
}
}
} // namespace logmessage
} // namespace oceanbase
此差异已折叠。
此差异已折叠。
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
oblogmsg is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
#include "MsgType.h"
#include <typeinfo>
#include <cstring>
namespace oceanbase {
namespace logmessage {
// typename => type
static struct {
const char* tn;
int vt;
} g_nameTypeMap[] = {{typeid(bool).name(), DT_INT8},
{typeid(char).name(), DT_INT8},
{typeid(int8_t).name(), DT_INT8},
{typeid(uint8_t).name(), DT_UINT8},
{typeid(int16_t).name(), DT_INT16},
{typeid(uint16_t).name(), DT_UINT16},
{typeid(int32_t).name(), DT_INT32},
{typeid(uint32_t).name(), DT_UINT32},
{typeid(int64_t).name(), DT_INT64},
{typeid(uint64_t).name(), DT_UINT64},
{typeid(long).name(), DT_INT64},
{typeid(unsigned long).name(), DT_UINT64},
{typeid(float).name(), DT_FLOAT},
{typeid(double).name(), DT_DOUBLE},
{0}};
int MsgType::getValType(const char* typeName)
{
for (int i = 0; g_nameTypeMap[i].tn != NULL; ++i) {
if (strcmp(g_nameTypeMap[i].tn, typeName) == 0) {
return g_nameTypeMap[i].vt;
}
}
return DT_UNKNOWN;
}
} // namespace logmessage
} // namespace oceanbase
此差异已折叠。
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
oblogmsg is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
#ifndef _MSG_VAR_AREA_H_
#define _MSG_VAR_AREA_H_
#include "StrArray.h"
#include "MsgType.h"
#include "MsgHeader.h"
#include <cstdio>
#include <string>
#include <vector>
#include <typeinfo>
#include "BinLogBuf.h"
namespace oceanbase {
namespace logmessage {
// ---------- Header ------------
struct VarAreaHeader {
MsgHeader m_msgHeader;
COUNT_TYPE m_count;
};
class MsgVarArea {
public:
MsgVarArea(bool creating = true);
MsgVarArea(const void* ptr, size_t size);
~MsgVarArea()
{}
// methods for creating
template <typename T>
size_t append(T val)
{
return append(typeid(T).name(), (const void*)&val, sizeof(T));
}
template <typename T>
size_t appendStringArray(T& sa);
size_t appendString(const char* s);
size_t appendData(const std::string& s);
static std::string createStringArrayData(
const char** sa, COUNT_TYPE count, STRLEN_TYPE* slen, bool appendTail, bool appendAlway);
size_t appendString(const char* s, size_t length);
size_t appendString(std::string* s);
size_t appendStringArray(const BinLogBuf* sa, size_t size);
size_t appendStringArray(const char** sa, size_t size);
static std::string createStringArrayData(const char** sa, size_t size);
static std::string createStringArrayData(std::vector<std::string*>& sa);
static std::string createStringArrayData(std::vector<std::string>& sa);
static std::string createStringArrayData(std::vector<const char*>& sa);
template <typename T>
size_t appendArray(T* a, size_t size)
{
return appendArray(typeid(T).name(), (const void*)a, sizeof(T), size);
}
template <typename T>
static std::string createArrayData(T* a, size_t size)
{
return createArray(typeid(T).name(), (const void*)a, sizeof(T), size);
}
const std::string& getMessage();
private:
size_t append(const char* typeName, const void* ptr, size_t size); // return offset
size_t appendArray(const char* typeName, const void* a, size_t elSize, size_t count);
static std::string createArray(const char* typeName, const void* a, size_t elSize, size_t count);
void afterAppending();
public:
// methods for fetching
void clear();
size_t getRealSize();
const void* getMsgBuf(size_t& size);
int parse(const void* ptr, size_t size);
int copy(const void* ptr, size_t size);
int getField(size_t offset, const void*& ptr, size_t& size);
int getString(size_t offset, const char*& s, size_t& length);
const char* getString(size_t offset);
void getString(size_t offset, const int off, char*& v, size_t& size);
StrArray* getStringArray(size_t offset);
int getStringArray(size_t offset, const char*& saPtr, size_t& count, const OFFSET_TYPE*& offsets);
int getArray(size_t offset, const void*& a, size_t& elSize, size_t& size);
int getBuf(size_t offset, const void*& a, size_t& size);
void getStringArrayData(unsigned int offset, const char*& v, size_t& size);
private:
COUNT_TYPE m_count;
std::string m_data; // save header data
const char* m_ptr;
size_t m_size;
bool m_creating;
bool m_parsedOK;
VarAreaHeader* m_areaHeader;
const char* m_areaPtr; // data begin
size_t m_areaSize; // data size
const char* m_areaEnd; // data end
};
} // namespace logmessage
} // namespace oceanbase
#endif
Subproject commit ff21b36e1e858bf9274ed2bbf4921e415363c393
add_executable(lr_unittest lrTest.cpp)
target_link_libraries(lr_unittest PRIVATE oblogmsg_shared gtest)
add_executable(varArea_unittest varAreaTest.cpp)
target_include_directories(varArea_unittest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../src)
target_link_libraries(varArea_unittest PRIVATE oblogmsg_shared gtest)
add_executable(md_unittest mdTest.cpp)
target_link_libraries(md_unittest PRIVATE oblogmsg_shared gtest)
add_executable(fa_unittest faTest.cpp)
target_link_libraries(fa_unittest PRIVATE oblogmsg_shared gtest)
add_executable(memoryleak_unittest memoryleakTest.cpp)
target_link_libraries(memoryleak_unittest PRIVATE oblogmsg_shared gtest)
enable_testing()
add_test(lr_unittest lr_unittest)
add_test(md_unittest md_unittest)
add_test(fa_unittest fa_unittest)
add_test(varArea_unittest varArea_unittest)
add_test(memoryleak_unittest memoryleak_unittest)
#include "MetaInfo.h"
#include "LogRecord.h"
#include "LogMsgFactory.h"
#include <gtest/gtest.h>
using namespace oceanbase::logmessage;
TEST(LogMsgFactory, LogMsgFactoryAPI)
{
IColMeta* colMeta = LogMsgFactory::createColMeta();
ASSERT_NE((void*)NULL, (void*)colMeta);
ITableMeta* tableMeta = LogMsgFactory::createTableMeta();
ASSERT_NE((void*)NULL, (void*)tableMeta);
IDBMeta* dbMeta = LogMsgFactory::createDBMeta();
ASSERT_NE((void*)NULL, (void*)dbMeta);
IMetaDataCollections* meta = LogMsgFactory::createMetaDataCollections();
ASSERT_NE((void*)NULL, (void*)meta);
ILogRecord* record = LogMsgFactory::createLogRecord("LogRecordImpl",true);
ASSERT_NE((void*)NULL, (void*)record);
LogMsgFactory::destroy(colMeta);
ASSERT_EQ((void*)NULL, (void*)colMeta);
LogMsgFactory::destroy(tableMeta);
ASSERT_EQ((void*)NULL, (void*)tableMeta);
LogMsgFactory::destroy(dbMeta);
ASSERT_EQ((void*)NULL, (void*)dbMeta);
LogMsgFactory::destroy(meta);
ASSERT_EQ((void*)NULL, (void*)meta);
LogMsgFactory::destroy(record);
ASSERT_EQ((void*)NULL, (void*)record);
LogMsgFactory::destroy(record);
ASSERT_EQ((void*)NULL, (void*)record);
}
int main(int argc, char* argv[])
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
此差异已折叠。
#include "MetaInfo.h"
#include "StrArray.h"
#include <stdio.h>
#include <gtest/gtest.h>
#include <vector>
#include <string>
#define COLN "col1"
#define COLT 253
#define COLL 4000
#define COLS false
#define PK true
#define UK false
#define NN true
#define DEF "default value for col1"
#define ENC "utf-8"
#define SMP(a, b) strcmp((a), (b))
using namespace oceanbase::logmessage;
IColMeta* createColMeta()
{
IColMeta* colMeta = new IColMeta;
colMeta->setName(COLN);
colMeta->setType(COLT);
colMeta->setLength(COLL);
colMeta->setSigned(COLS);
colMeta->setIsPK(PK);
colMeta->setIsUK(UK);
colMeta->setNotNull(NN);
colMeta->setDefault(DEF);
colMeta->setEncoding(ENC);
std::vector<std::string> sets;
sets.push_back("set1");
sets.push_back("set2");
colMeta->setValuesOfEnumSet(sets);
return colMeta;
}
void cmpColMeta(IColMeta& colMeta, std::vector<std::string>& sets)
{
ASSERT_EQ(0, SMP(COLN, colMeta.getName()));
ASSERT_EQ(COLT, colMeta.getType());
ASSERT_EQ(COLL, colMeta.getLength());
ASSERT_EQ(COLS, colMeta.isSigned());
ASSERT_EQ(PK, colMeta.isPK());
ASSERT_EQ(UK, colMeta.isUK());
ASSERT_EQ(NN, colMeta.isNotNull());
ASSERT_EQ(0, SMP(DEF, colMeta.getDefault()));
ASSERT_EQ(0, SMP(ENC, colMeta.getEncoding()));
StrArray* serializedSets = colMeta.getValuesOfEnumSet();
ASSERT_NE((void*)NULL, (void*)serializedSets);
ASSERT_EQ(0, SMP(sets[0].c_str(), (*serializedSets)[0]));
ASSERT_EQ(0, SMP(sets[1].c_str(), (*serializedSets)[1]));
delete serializedSets;
}
TEST(IColMeta, IColMetaAPI)
{
IColMeta* colMeta = createColMeta();
/* Prepare the column meta */
std::vector<std::string> sets;
sets.push_back("set1");
sets.push_back("set2");
cmpColMeta(*colMeta, sets);
/* Compare with parsed one */
std::string s;
ASSERT_EQ(0, colMeta->appendTo(s));
IColMeta parser(s.c_str(), s.size());
size_t msgSize = s.size();
ASSERT_EQ(msgSize, parser.getRealSize());
cmpColMeta(parser, sets);
delete colMeta;
}
#define TN "table1"
ITableMeta* createTableMeta()
{
ITableMeta* tableMeta = new ITableMeta;
tableMeta->setName(TN);
tableMeta->setHasPK(PK);
tableMeta->setHasUK(UK);
tableMeta->setEncoding(ENC);
tableMeta->setDBMeta(NULL);
return tableMeta;
}
void cmpTableMeta(ITableMeta& tableMeta)
{
ASSERT_EQ(0, SMP(TN, tableMeta.getName()));
ASSERT_EQ(PK, tableMeta.hasPK());
ASSERT_EQ(UK, tableMeta.hasUK());
ASSERT_EQ(0, SMP(ENC, tableMeta.getEncoding()));
ASSERT_EQ((void*)NULL, (void*)tableMeta.getDBMeta());
}
TEST(ITableMeta, ITableMetaAPI)
{
// Prepare the table meta
ITableMeta* tableMeta = createTableMeta();
IColMeta* colMeta = createColMeta();
tableMeta->append(colMeta->getName(), colMeta);
// Compare column meta
ASSERT_EQ(colMeta, tableMeta->getCol(0));
ASSERT_EQ(colMeta, tableMeta->getCol(COLN));
std::vector<std::string>& colNames = tableMeta->getColNames();
ASSERT_EQ((size_t)1, colNames.size());
ASSERT_EQ(0, SMP(COLN, colNames[0].c_str()));
// Compare with parsed tablemeta
std::string s;
ASSERT_EQ(0, tableMeta->appendTo(s));
ITableMeta parser(s.c_str(), s.size());
std::string c;
ASSERT_EQ(0, colMeta->appendTo(c));
IColMeta colParser(c.c_str(), c.size());
ASSERT_EQ(s.size(), parser.getRealSize() + colParser.getRealSize());
cmpTableMeta(parser);
delete tableMeta;
}
#define DBN "db1"
IDBMeta* createDBMeta()
{
IDBMeta* dbMeta = new IDBMeta();
dbMeta->setName(DBN);
dbMeta->setEncoding(ENC);
dbMeta->setMetaDataCollections(NULL);
return dbMeta;
}
void cmpDBMeta(IDBMeta* dbMeta)
{
ASSERT_NE((void*)NULL, (void*)dbMeta);
ASSERT_EQ(0, SMP(DBN, dbMeta->getName()));
ASSERT_EQ(0, SMP(ENC, dbMeta->getEncoding()));
ASSERT_EQ((void*)NULL, (void*)dbMeta->getMetaDataCollections());
}
TEST(IDBMeta, IDBMetaAPI)
{
IDBMeta* dbMeta = createDBMeta();
cmpDBMeta(dbMeta);
delete dbMeta;
}
TEST(IMetaDataCollections, IMetaDataCollectionsAPI)
{
IMetaDataCollections* meta = new IMetaDataCollections;
ASSERT_NE((void*)NULL, (void*)meta);
delete meta;
}
int main(int argc, char* argv[])
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
此差异已折叠。
此差异已折叠。