blob: 154c2c0dceb089c6e2dd17c31b29419ec904b712 [file]
/*-------------------------------------------------------------------------
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* EventSender.h
*
* IDENTIFICATION
* gpcontrib/gp_stats_collector/src/EventSender.h
*
*-------------------------------------------------------------------------
*/
#pragma once
#include <memory>
#include <unordered_map>
#include <tuple>
#define typeid __typeid
extern "C" {
#include "utils/metrics_utils.h"
#ifdef IC_TEARDOWN_HOOK
#include "cdb/ic_udpifc.h"
#endif
}
#undef typeid
#include "memory/gpdbwrappers.h"
#include "Config.h"
class UDSConnector;
struct QueryDesc;
namespace gpsc {
class SetQueryReq;
}
#include <cstdint>
extern void gp_gettmid(int32 *);
struct QueryKey {
int tmid;
int ssid;
int ccnt;
int nesting_level;
uintptr_t query_desc_addr;
bool operator==(const QueryKey &other) const {
return std::tie(tmid, ssid, ccnt, nesting_level, query_desc_addr) ==
std::tie(other.tmid, other.ssid, other.ccnt, other.nesting_level,
other.query_desc_addr);
}
static void register_qkey(QueryDesc *query_desc, size_t nesting_level) {
query_desc->gpsc_query_key =
(GpscQueryKey *)gpdb::palloc0(sizeof(GpscQueryKey));
int32 tmid;
gp_gettmid(&tmid);
query_desc->gpsc_query_key->tmid = tmid;
query_desc->gpsc_query_key->ssid = gp_session_id;
query_desc->gpsc_query_key->ccnt = gp_command_count;
query_desc->gpsc_query_key->nesting_level = nesting_level;
query_desc->gpsc_query_key->query_desc_addr = (uintptr_t)query_desc;
}
static QueryKey from_qdesc(QueryDesc *query_desc) {
return {
.tmid = query_desc->gpsc_query_key->tmid,
.ssid = query_desc->gpsc_query_key->ssid,
.ccnt = query_desc->gpsc_query_key->ccnt,
.nesting_level = query_desc->gpsc_query_key->nesting_level,
.query_desc_addr = query_desc->gpsc_query_key->query_desc_addr,
};
}
};
// https://www.boost.org/doc/libs/1_35_0/doc/html/boost/hash_combine_id241013.html
template <class T> inline void hash_combine(std::size_t &seed, const T &v) {
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
namespace std {
template <> struct hash<QueryKey> {
size_t operator()(const QueryKey &k) const noexcept {
size_t seed = hash<uint32_t>{}(k.tmid);
hash_combine(seed, k.ssid);
hash_combine(seed, k.ccnt);
hash_combine(seed, k.nesting_level);
uintptr_t addr = k.query_desc_addr;
if constexpr (SIZE_MAX < UINTPTR_MAX) {
addr %= SIZE_MAX;
}
hash_combine(seed, addr);
return seed;
}
};
} // namespace std
class EventSender {
public:
void executor_before_start(QueryDesc *query_desc, int eflags);
void executor_after_start(QueryDesc *query_desc, int eflags);
void executor_end(QueryDesc *query_desc);
void query_metrics_collect(QueryMetricsStatus status, void *arg, bool utility,
ErrorData *edata = NULL);
void ic_metrics_collect();
void analyze_stats_collect(QueryDesc *query_desc);
void incr_depth() { nesting_level++; }
void decr_depth() { nesting_level--; }
EventSender();
~EventSender();
private:
enum QueryState { SUBMIT, START, END, DONE };
struct QueryItem {
std::unique_ptr<gpsc::SetQueryReq> message;
QueryState state;
explicit QueryItem(QueryState st);
};
bool log_query_req(const gpsc::SetQueryReq &req, const std::string &event,
bool utility);
bool verify_query(QueryDesc *query_desc, QueryState state, bool utility);
void update_query_state(QueryItem &query, QueryState new_state, bool utility,
bool success = true);
QueryItem &get_query(QueryDesc *query_desc);
void submit_query(QueryDesc *query_desc);
void collect_query_submit(QueryDesc *query_desc, bool utility);
void report_query_done(QueryDesc *query_desc, QueryItem &query,
QueryMetricsStatus status, bool utility,
ErrorData *edata = NULL);
void collect_query_done(QueryDesc *query_desc, bool utility,
QueryMetricsStatus status, ErrorData *edata = NULL);
void update_nested_counters(QueryDesc *query_desc);
bool qdesc_submitted(QueryDesc *query_desc);
bool nesting_is_valid(QueryDesc *query_desc, int nesting_level);
bool need_report_nested_query();
bool filter_query(QueryDesc *query_desc);
bool proto_verified = false;
int nesting_level = 0;
int64_t nested_calls = 0;
double nested_timing = 0;
#ifdef IC_TEARDOWN_HOOK
ICStatistics ic_statistics;
#endif
std::unordered_map<QueryKey, QueryItem> queries;
Config config;
};