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
SqlStatistic(const std::string & sql,int32_t step,uint32_t seqId)53 SqlStatistic::SqlStatistic(const std::string &sql, int32_t step, uint32_t seqId)
54 {
55 if (!enabled_) {
56 return;
57 }
58 step_ = step;
59 key_ = seqId == 0 ? GetThreadId() : uint64_t(seqId);
60 time_ = std::chrono::steady_clock::now();
61 auto it = execInfos_.Find(key_);
62 if (it.first) {
63 execInfo_ = it.second;
64 }
65
66 if (execInfo_ == nullptr && seqId != 0) {
67 it = execInfos_.Find(GetThreadId());
68 execInfo_ = it.second;
69 }
70
71 if (execInfo_ == nullptr) {
72 execInfo_ = std::shared_ptr<SqlExecInfo>(new (std::nothrow) SqlExecInfo(), Release);
73 execInfos_.Insert(key_, execInfo_);
74 }
75
76 if (step_ == STEP_PREPARE && !sql.empty()) {
77 execInfo_->sql_.emplace_back(sql);
78 }
79 }
80
~SqlStatistic()81 SqlStatistic::~SqlStatistic()
82 {
83 if (!enabled_) {
84 return;
85 }
86 if (execInfo_ == nullptr) {
87 return;
88 }
89 auto interval = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - time_);
90 switch (step_) {
91 case STEP_WAIT:
92 execInfo_->waitTime_ += interval.count();
93 break;
94 case STEP_PREPARE:
95 execInfo_->prepareTime_ += interval.count();
96 break;
97 case STEP_EXECUTE:
98 execInfo_->executeTime_ += interval.count();
99 break;
100 case STEP_TOTAL:
101 case STEP_TOTAL_RES:
102 execInfo_->totalTime_ += interval.count();
103 execInfos_.Erase(key_);
104 break;
105 default:
106 execInfo_->totalTime_ += interval.count();
107 break;
108 }
109 }
110
Release(SqlExecInfo * execInfo)111 void SqlStatistic::Release(SqlExecInfo *execInfo)
112 {
113 if (execInfo == nullptr) {
114 return;
115 }
116 if (execInfo->sql_.empty()) {
117 delete execInfo;
118 return;
119 }
120 auto executor = TaskExecutor::GetInstance().GetExecutor();
121 if (executor == nullptr) {
122 delete execInfo;
123 return;
124 }
125 executor->Execute([info = std::move(*execInfo)]() {
126 observers_.ForEachCopies([&info](auto key, std::shared_ptr<SqlObserver> &observer) {
127 if (observer == nullptr) {
128 return false;
129 }
130 observer->OnStatistic(info);
131 return false;
132 });
133 });
134 delete execInfo;
135 }
136 }