/* * Copyright [2021] JD.com, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CH_SECTION_H__ #define __CH_SECTION_H__ #include "mem_check.h" #include #include #include #include #include "value.h" #include "protocol.h" #include "log/log.h" #define MAX_STATIC_SECTION 20 /* * tag: a pair of id:value, the value type if predefined * section: a set of id:value */ struct SectionDefinition { uint8_t sectionId; uint8_t maxTags; uint8_t tagType[256]; uint8_t tag_type(uint8_t i) const { return tagType[i]; }; int max_tags(void) const { return maxTags; } int section_id(void) const { return sectionId; } }; class SimpleSection { private: const SectionDefinition *definition; uint8_t numTags; #if MAX_STATIC_SECTION uint8_t fieldMask[(MAX_STATIC_SECTION + 7) / 8]; #else uint8_t fieldMask[32]; #endif public: #if MAX_STATIC_SECTION DTCValue tagValue[MAX_STATIC_SECTION]; #else DTCValue *tagValue; #endif SimpleSection(const SectionDefinition &d) : definition(&d), numTags(0) { #if MAX_STATIC_SECTION for (int i = 0; i < d.max_tags(); i++) tagValue[i].Set(NULL, 0); #else tagValue = (DTCValue *)calloc(d.max_tags(), sizeof(DTCValue)); if (tagValue == NULL) throw std::bad_alloc(); #endif FIELD_ZERO(fieldMask); } virtual ~SimpleSection() { #if !MAX_STATIC_SECTION FREE_IF(tagValue); #endif } SimpleSection(const SimpleSection &orig) { #if !MAX_STATIC_SECTION tagValue = (DTCValue *)malloc(orig.definition->max_tags(), sizeof(DTCValue)); if (tagValue == NULL) throw std::bad_alloc(); #endif Copy(orig); } void Copy(const SimpleSection &orig) { for (int i = 0; i < orig.definition->max_tags(); i++) tagValue[i] = orig.tagValue[i]; memcpy(fieldMask, orig.fieldMask, sizeof(fieldMask)); definition = orig.definition; numTags = orig.numTags; } inline virtual void Clean() { memset(tagValue, 0, sizeof(DTCValue) * definition->max_tags()); FIELD_ZERO(fieldMask); numTags = 0; } int max_tags(void) const { return definition->max_tags(); } int num_tags(void) const { return numTags; } int section_id(void) const { return definition->section_id(); } uint8_t tag_type(uint8_t id) const { return definition->tag_type(id); } int tag_present(uint8_t id) const { return id >= MAX_STATIC_SECTION ? 0 : FIELD_ISSET(id, fieldMask); } void set_tag(uint8_t id, const DTCValue &val) { if (tag_type(id) != DField::None) { tagValue[id] = val; if (!FIELD_ISSET(id, fieldMask)) { numTags++; FIELD_SET(id, fieldMask); } } } /* no check of dumplicate tag */ void SetTagMask(uint8_t id) { numTags++; FIELD_SET(id, fieldMask); } void set_tag(uint8_t id, int64_t val) { set_tag(id, DTCValue::Make(val)); } void set_tag(uint8_t id, uint64_t val) { set_tag(id, DTCValue::Make(val)); } void set_tag(uint8_t id, int32_t val) { if (tag_type(id) == DField::Signed) set_tag(id, DTCValue::Make(val)); else if (tag_type(id) == DField::Unsigned) { if (val < 0) val = 0; set_tag(id, DTCValue::Make((uint64_t)val)); } } void set_tag(uint8_t id, uint32_t val) { //fix Unsigned to Signed if (tag_type(id) == DField::Signed) set_tag(id, DTCValue::Make((int64_t)val)); else if (tag_type(id) == DField::Unsigned) set_tag(id, DTCValue::Make(val)); } void set_tag(uint8_t id, double val) { if (tag_type(id) == DField::Float) set_tag(id, DTCValue::Make(val)); } void set_tag(uint8_t id, const char *val, int len) { if (tag_type(id) == DField::String || tag_type(id) == DField::Binary) set_tag(id, DTCValue::Make(val, len)); } void set_tag(uint8_t id, const char *val) { if (tag_type(id) == DField::String || tag_type(id) == DField::Binary) set_tag(id, DTCValue::Make(val)); } const DTCValue *get_tag(uint8_t id) const { return tag_present(id) ? &tagValue[id] : NULL; } /* no check */ DTCValue *get_this_tag(uint8_t id) { return &tagValue[id]; } const DTCValue *key(void) const { return tag_present(0) ? &tagValue[0] : NULL; } void set_key(const DTCValue &k) { set_tag(0, k); } }; extern const SectionDefinition versionInfoDefinition; extern const SectionDefinition requestInfoDefinition; extern const SectionDefinition resultInfoDefinition; class DTCVersionInfo : public SimpleSection { public: DTCVersionInfo() : SimpleSection(versionInfoDefinition) { } ~DTCVersionInfo() { } DTCVersionInfo(const DTCVersionInfo &orig) : SimpleSection(orig) { } const DTCBinary &table_name(void) const { return tagValue[1].str; } void set_table_name(const char *n) { set_tag(1, n); } const DTCBinary &table_hash(void) const { return tagValue[4].str; } void set_table_hash(const char *n) { set_tag(4, n, 16); } const DTCBinary &data_table_hash(void) const { return tagValue[2].str; } void set_data_table_hash(const char *n) { set_tag(2, n, 16); } const DTCBinary &CTLibVer(void) const { return tagValue[6].str; } const int CTLibIntVer(void) const { int major = 3; //, minor=0, micro=0; /* 3.x系列的批量拆包之后没有version信息 */ if (NULL == CTLibVer().ptr) { log4cplus_debug("multi job have no version info"); return major; } char buf = CTLibVer().ptr[7]; if (buf >= '1' && buf <= '9') { major = buf - '0'; log4cplus_debug( "client major version:%d,version string:%s", major, CTLibVer().ptr); return major; } else { log4cplus_debug("unknown client api version: %s", CTLibVer().ptr); return major; } } int ReConnect(void) const { return tagValue[19].u64; } int key_type(void) const { return tagValue[9].u64; } void set_key_type(int n) { set_tag(9, n); } #if MAX_STATIC_SECTION >= 1 && MAX_STATIC_SECTION < 10 #error MAX_STATIC_SECTION must >= 10 #endif const uint64_t serial_nr(void) const { return tagValue[3].u64; } void set_serial_nr(uint64_t u) { set_tag(3, u); } const int keep_alive_timeout(void) const { return (int)tagValue[8].u64; } void set_keep_alive_timeout(uint32_t u) { set_tag(8, u); } void set_hot_backup_id(uint64_t u) { set_tag(14, u); } uint64_t hot_backup_id() const { return tagValue[14].u64; } void set_master_hb_timestamp(int64_t t) { set_tag(15, t); } int64_t master_hb_timestamp(void) const { return tagValue[15].s64; } void set_slave_hb_timestamp(int64_t t) { set_tag(16, t); } int64_t slave_hb_timestamp(void) const { return tagValue[16].s64; } uint64_t get_agent_client_id() const { return tagValue[17].u64; } void set_agent_client_id(uint64_t id) { set_tag(17, id); } void set_access_key(const char *token) { set_tag(18, token); } const DTCBinary &access_key(void) const { return tagValue[18].str; } }; class DTCRequestInfo : public SimpleSection { public: DTCRequestInfo() : SimpleSection(requestInfoDefinition) { } ~DTCRequestInfo() { } DTCRequestInfo(const DTCRequestInfo &orig) : SimpleSection(orig) { } uint64_t get_expire_time(int version) const { /* server内部全部按照ms单位来处理超时 */ if (version >= 3) /* 3.x 系列客户端发送的超时时间单位:us */ return tagValue[1].u64 >> 10; else /* 2.x 系列客户端发送的超时时间单位: ms */ return tagValue[1].u64; } void set_timeout(uint32_t n) { set_tag(1, (uint64_t)n << 10); } uint32_t limit_start(void) const { return tagValue[2].u64; } uint32_t limit_count(void) const { return tagValue[3].u64; } void set_limit_start(uint32_t n) { set_tag(2, (uint64_t)n); } void set_limit_count(uint32_t n) { set_tag(3, (uint64_t)n); } uint32_t admin_code() const { return tagValue[7].u64; } void set_admin_code(uint32_t code) { set_tag(7, (uint64_t)code); } }; class DTCResultInfo : public SimpleSection { private: char *szErrMsg; char *s_info; char *t_info; public: DTCResultInfo() : SimpleSection(resultInfoDefinition), szErrMsg(NULL), s_info(NULL), t_info(NULL) { } ~DTCResultInfo() { FREE_CLEAR(szErrMsg); FREE_CLEAR(s_info); FREE_CLEAR(t_info); } DTCResultInfo(const DTCResultInfo &orig) : SimpleSection(orig) { if (orig.szErrMsg) { szErrMsg = STRDUP(orig.szErrMsg); set_tag(3, szErrMsg, strlen(szErrMsg)); } if (orig.s_info) { s_info = NULL; set_server_info((DTCServerInfo *)orig.s_info); } if (orig.t_info) { t_info = NULL; set_time_info((DTCTimeInfo *)orig.t_info); } } inline virtual void Clean() { SimpleSection::Clean(); FREE_CLEAR(szErrMsg); FREE_CLEAR(s_info); FREE_CLEAR(t_info); } void Copy(const DTCResultInfo &orig) { SimpleSection::Copy(orig); FREE_CLEAR(szErrMsg); if (orig.szErrMsg) { szErrMsg = STRDUP(orig.szErrMsg); set_tag(3, szErrMsg, strlen(szErrMsg)); } FREE_CLEAR(s_info); if (orig.s_info) { set_server_info((DTCServerInfo *)orig.s_info); } FREE_CLEAR(t_info); if (orig.t_info) { set_time_info((DTCTimeInfo *)orig.t_info); } } void set_error(int err, const char *from, const char *msg) { set_tag(1, err); if (from) set_tag(2, (char *)from, strlen(from)); if (msg) set_tag(3, (char *)msg, strlen(msg)); } void set_error_dup(int err, const char *from, const char *msg) { FREE_IF(szErrMsg); szErrMsg = STRDUP(msg); set_tag(1, err); if (from) set_tag(2, (char *)from, strlen(from)); if (msg) set_tag(3, szErrMsg, strlen(szErrMsg)); } int result_code(void) const { return tagValue[1].s64; } const char *error_from(void) const { return tagValue[2].str.ptr; } const char *error_message(void) const { return tagValue[3].str.ptr; } uint64_t affected_rows(void) const { return tagValue[4].s64; } void set_affected_rows(uint64_t nr) { set_tag(4, nr); } uint64_t total_rows(void) const { return tagValue[5].s64; } void set_total_rows(uint64_t nr) { set_tag(5, nr); } uint64_t insert_id(void) const { return tagValue[6].u64; } void set_insert_id(uint64_t nr) { set_tag(6, nr); } char *server_info(void) const { if (tagValue[7].str.len != sizeof(DTCServerInfo)) return NULL; return tagValue[7].str.ptr; } void set_server_info(DTCServerInfo *si) { FREE_IF(s_info); int len = sizeof(DTCServerInfo); s_info = (char *)CALLOC(1, len); memcpy(s_info, si, len); set_tag(7, s_info, len); return; } char *time_info(void) const { if (tagValue[7].str.len != sizeof(DTCTimeInfo)) return NULL; return tagValue[7].str.ptr; } void set_time_info(DTCTimeInfo *ti) { FREE_IF(t_info); int len = sizeof(DTCTimeInfo); t_info = (char *)CALLOC(1, len); memcpy(t_info, ti, len); set_tag(7, t_info, len); return; } uint32_t Timestamp(void) const { return tagValue[8].s64; } void set_time_info(uint32_t nr) { set_tag(8, nr); } /*set hit flag by tomchen 20140604*/ void set_hit_flag(uint32_t nr) { set_tag(9, nr); } uint32_t hit_flag() const { return tagValue[9].s64; }; /*一个请求有多个key的时候,要统计这个请求不同key对应的业务命中率和计数命中率*/ /*命中率字段中,前16位放业务命中率,后16位放技术命中率*/ uint32_t get_tech_hit_num() { uint32_t uHitFlag = (uint32_t)hit_flag(); uint32_t uTaskTechHitNum = uHitFlag & 0xFFFF; return uTaskTechHitNum; } uint32_t get_business_hit_num() { uint32_t uHitFlag = (uint32_t)hit_flag(); uint32_t uTashBusinessHitNum = (uHitFlag & 0xFFFF0000) >> 16; return uTashBusinessHitNum; } void incr_tech_hit_num() { uint32_t uHitFlag = (uint32_t)hit_flag(); uint32_t uTaskTechHitNum = uHitFlag & 0xFFFF; uTaskTechHitNum++; uHitFlag = uHitFlag & 0xFFFF0000; uHitFlag = uHitFlag | uTaskTechHitNum; set_hit_flag(uHitFlag); } void incr_bussiness_hit_num() { uint32_t uHitFlag = (uint32_t)hit_flag(); uint32_t uTashBusinessHitNum = (uHitFlag & 0xFFFF0000) >> 16; uTashBusinessHitNum++; uTashBusinessHitNum = uTashBusinessHitNum << 16; uHitFlag = uHitFlag & 0xFFFF; uHitFlag = uHitFlag | uTashBusinessHitNum; set_hit_flag(uHitFlag); } }; #endif