1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #define LOG_TAG "RdbSqlStatistic"
17
18 #include "rdb_sql_statistic.h"
19
20 #include <thread>
21
22 #include "concurrent_map.h"
23 #include "logger.h"
24 #include "rdb_errno.h"
25 #include "rdb_platform.h"
26 #include "task_executor.h"
27 namespace OHOS::DistributedRdb {
28 using namespace OHOS::Rdb;
29 using namespace OHOS::NativeRdb;
30 ConcurrentMap<SqlObserver *, std::shared_ptr<SqlObserver>> SqlStatistic::observers_;
31 ConcurrentMap<uint64_t, std::shared_ptr<SqlObserver::SqlExecutionInfo>> SqlStatistic::execInfos_;
32 bool SqlStatistic::enabled_ = false;
33 std::atomic_uint32_t SqlStatistic::seqId_ = 0;
Subscribe(std::shared_ptr<SqlObserver> observer)34 int SqlStatistic::Subscribe(std::shared_ptr<SqlObserver> observer)
35 {
36 observers_.ComputeIfAbsent(observer.get(), [observer](auto &) {
37 enabled_ = true;
38 return observer;
39 });
40 return E_OK;
41 }
42
Unsubscribe(std::shared_ptr<SqlObserver> observer)43 int SqlStatistic::Unsubscribe(std::shared_ptr<SqlObserver> observer)
44 {
45 observers_.Erase(observer.get());
46 observers_.DoActionIfEmpty([]() {
47 enabled_ = false;
48 execInfos_.Clear();
49 });
50 return E_OK;
51 }
52
GenerateId()53 uint32_t SqlStatistic::GenerateId()
54 {
55 return ++seqId_;
56 }
57
SqlStatistic(const std::string & sql,int32_t step,uint32_t seqId)58 SqlStatistic::SqlStatistic(const std::string &sql, int32_t step, uint32_t seqId)
59 {
60 if (!enabled_) {
61 return;
62 }
63 step_ = step;
64 key_ = seqId == 0 ? GetThreadId() : uint64_t(seqId);
65 time_ = std::chrono::steady_clock::now();
66 auto it = execInfos_.Find(key_);
67 if (it.first) {
68 execInfo_ = it.second;
69 }
70
71 if (execInfo_ == nullptr && seqId != 0) {
72 it = execInfos_.Find(GetThreadId());
73 execInfo_ = it.second;
74 }
75
76 if (execInfo_ == nullptr) {
77 execInfo_ = std::shared_ptr<SqlExecInfo>(new (std::nothrow) SqlExecInfo(), Release);
78 execInfos_.Insert(key_, execInfo_);
79 }
80
81 if (step_ == STEP_PREPARE && !sql.empty()) {
82 execInfo_->sql_.emplace_back(sql);
83 }
84 }
85
~SqlStatistic()86 SqlStatistic::~SqlStatistic()
87 {
88 if (!enabled_) {
89 return;
90 }
91 if (execInfo_ == nullptr) {
92 return;
93 }
94 auto interval = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - time_);
95 switch (step_) {
96 case STEP_WAIT:
97 execInfo_->waitTime_ += interval.count();
98 break;
99 case STEP_PREPARE:
100 execInfo_->prepareTime_ += interval.count();
101 break;
102 case STEP_EXECUTE:
103 execInfo_->executeTime_ += interval.count();
104 break;
105 case STEP_TOTAL:
106 case STEP_TOTAL_RES:
107 execInfo_->totalTime_ += interval.count();
108 execInfos_.Erase(key_);
109 break;
110 default:
111 execInfo_->totalTime_ += interval.count();
112 break;
113 }
114 }
115
Release(SqlExecInfo * execInfo)116 void SqlStatistic::Release(SqlExecInfo *execInfo)
117 {
118 if (execInfo == nullptr) {
119 return;
120 }
121 if (execInfo->sql_.empty()) {
122 delete execInfo;
123 return;
124 }
125 auto executor = TaskExecutor::GetInstance().GetExecutor();
126 if (executor == nullptr) {
127 delete execInfo;
128 return;
129 }
130 executor->Execute([info = std::move(*execInfo)]() {
131 observers_.ForEachCopies([&info](auto key, std::shared_ptr<SqlObserver> &observer) {
132 if (observer == nullptr) {
133 return false;
134 }
135 observer->OnStatistic(info);
136 return false;
137 });
138 });
139 delete execInfo;
140 }
141 }