106f6ba60Sopenharmony_ci/*
206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved.
306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License.
506f6ba60Sopenharmony_ci * You may obtain a copy of the License at
606f6ba60Sopenharmony_ci *
706f6ba60Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
806f6ba60Sopenharmony_ci *
906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and
1306f6ba60Sopenharmony_ci * limitations under the License.
1406f6ba60Sopenharmony_ci */
1506f6ba60Sopenharmony_ci
1606f6ba60Sopenharmony_ci#include "buffer_writer.h"
1706f6ba60Sopenharmony_ci#include "command_poller.h"
1806f6ba60Sopenharmony_ci#include "common_types.pb.h"
1906f6ba60Sopenharmony_ci#include "logging.h"
2006f6ba60Sopenharmony_ci#include "plugin_service_types.pb.h"
2106f6ba60Sopenharmony_ci#include "share_memory_allocator.h"
2206f6ba60Sopenharmony_ci
2306f6ba60Sopenharmony_ci#include <algorithm>
2406f6ba60Sopenharmony_ci#include <cinttypes>
2506f6ba60Sopenharmony_ci#include <thread>
2606f6ba60Sopenharmony_ci#include <unistd.h>
2706f6ba60Sopenharmony_ci
2806f6ba60Sopenharmony_ciusing namespace OHOS::Developtools::Profiler;
2906f6ba60Sopenharmony_ci
3006f6ba60Sopenharmony_ciBufferWriter::BufferWriter(std::string name,
3106f6ba60Sopenharmony_ci                           std::string version,
3206f6ba60Sopenharmony_ci                           uint32_t size,
3306f6ba60Sopenharmony_ci                           int smbFd,
3406f6ba60Sopenharmony_ci                           int eventFd,
3506f6ba60Sopenharmony_ci                           uint32_t pluginId)
3606f6ba60Sopenharmony_ci    : pluginName_(name), pluginVersion_(version)
3706f6ba60Sopenharmony_ci{
3806f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "%s:%s %d [%d] [%d]", __func__, name.c_str(), size, smbFd, eventFd);
3906f6ba60Sopenharmony_ci    shareMemoryBlock_ = ShareMemoryAllocator::GetInstance().CreateMemoryBlockRemote(name, size, smbFd);
4006f6ba60Sopenharmony_ci    if (shareMemoryBlock_ == nullptr) {
4106f6ba60Sopenharmony_ci        PROFILER_LOG_DEBUG(LOG_CORE, "%s:create shareMemoryBlock_ failed!", __func__);
4206f6ba60Sopenharmony_ci    }
4306f6ba60Sopenharmony_ci    eventNotifier_ = EventNotifier::CreateWithFd(eventFd);
4406f6ba60Sopenharmony_ci    pluginId_ = pluginId;
4506f6ba60Sopenharmony_ci    lastFlushTime_ = std::chrono::steady_clock::now();
4606f6ba60Sopenharmony_ci    if (shareMemoryBlock_ != nullptr) {
4706f6ba60Sopenharmony_ci        writeCtx_ = reinterpret_cast<RandomWriteCtx*>(shareMemoryBlock_->GetCtx());
4806f6ba60Sopenharmony_ci        profilerPluginData_ = ProtoEncoder::ProfilerPluginData(writeCtx_);
4906f6ba60Sopenharmony_ci    }
5006f6ba60Sopenharmony_ci}
5106f6ba60Sopenharmony_ci
5206f6ba60Sopenharmony_ciBufferWriter::~BufferWriter()
5306f6ba60Sopenharmony_ci{
5406f6ba60Sopenharmony_ci    PROFILER_LOG_DEBUG(LOG_CORE, "%s:destroy eventfd = %d!", __func__, eventNotifier_ ? eventNotifier_->GetFd() : -1);
5506f6ba60Sopenharmony_ci    eventNotifier_ = nullptr;
5606f6ba60Sopenharmony_ci    ShareMemoryAllocator::GetInstance().ReleaseMemoryBlockRemote(pluginName_);
5706f6ba60Sopenharmony_ci}
5806f6ba60Sopenharmony_ci
5906f6ba60Sopenharmony_civoid BufferWriter::Report() const
6006f6ba60Sopenharmony_ci{
6106f6ba60Sopenharmony_ci    PROFILER_LOG_DEBUG(LOG_CORE, "%s:stats B: %" PRIu64 ", P: %d, W:%" PRIu64 ", F: %d", __func__,
6206f6ba60Sopenharmony_ci        bytesCount_.load(), bytesPending_.load(), writeCount_.load(), flushCount_.load());
6306f6ba60Sopenharmony_ci}
6406f6ba60Sopenharmony_ci
6506f6ba60Sopenharmony_civoid BufferWriter::DoStats(long bytes)
6606f6ba60Sopenharmony_ci{
6706f6ba60Sopenharmony_ci    ++writeCount_;
6806f6ba60Sopenharmony_ci    bytesCount_ += static_cast<uint64_t>(bytes);
6906f6ba60Sopenharmony_ci    bytesPending_ += static_cast<uint32_t>(bytes);
7006f6ba60Sopenharmony_ci}
7106f6ba60Sopenharmony_ci
7206f6ba60Sopenharmony_cilong BufferWriter::Write(const void* data, size_t size)
7306f6ba60Sopenharmony_ci{
7406f6ba60Sopenharmony_ci    if (shareMemoryBlock_ == nullptr || data == nullptr || size == 0) {
7506f6ba60Sopenharmony_ci        return false;
7606f6ba60Sopenharmony_ci    }
7706f6ba60Sopenharmony_ci    ProfilerPluginData pluginData;
7806f6ba60Sopenharmony_ci    pluginData.set_name(pluginName_);
7906f6ba60Sopenharmony_ci    pluginData.set_version(pluginVersion_);
8006f6ba60Sopenharmony_ci    pluginData.set_status(0);
8106f6ba60Sopenharmony_ci    pluginData.set_data(data, size);
8206f6ba60Sopenharmony_ci
8306f6ba60Sopenharmony_ci    struct timespec ts = { 0, 0 };
8406f6ba60Sopenharmony_ci    clock_gettime(clockId_, &ts);
8506f6ba60Sopenharmony_ci
8606f6ba60Sopenharmony_ci    pluginData.set_clock_id(static_cast<ProfilerPluginData_ClockId>(clockId_));
8706f6ba60Sopenharmony_ci    pluginData.set_tv_sec(ts.tv_sec);
8806f6ba60Sopenharmony_ci    pluginData.set_tv_nsec(ts.tv_nsec);
8906f6ba60Sopenharmony_ci
9006f6ba60Sopenharmony_ci    DoStats(pluginData.ByteSizeLong());
9106f6ba60Sopenharmony_ci    return shareMemoryBlock_->PutMessage(pluginData, pluginName_);
9206f6ba60Sopenharmony_ci}
9306f6ba60Sopenharmony_ci
9406f6ba60Sopenharmony_ciRandomWriteCtx* BufferWriter::StartReport()
9506f6ba60Sopenharmony_ci{
9606f6ba60Sopenharmony_ci    if (shareMemoryBlock_ == nullptr || writeCtx_ == nullptr) {
9706f6ba60Sopenharmony_ci        return nullptr;
9806f6ba60Sopenharmony_ci    }
9906f6ba60Sopenharmony_ci
10006f6ba60Sopenharmony_ci    shareMemoryBlock_->ResetPos();
10106f6ba60Sopenharmony_ci    profilerPluginData_.Reset(writeCtx_);
10206f6ba60Sopenharmony_ci    profilerPluginData_.set_name(pluginName_);
10306f6ba60Sopenharmony_ci    profilerPluginData_.set_version(pluginVersion_);
10406f6ba60Sopenharmony_ci    profilerPluginData_.set_status(0);
10506f6ba60Sopenharmony_ci    return profilerPluginData_.startAdd_data();
10606f6ba60Sopenharmony_ci}
10706f6ba60Sopenharmony_ci
10806f6ba60Sopenharmony_civoid BufferWriter::FinishReport(int32_t size)
10906f6ba60Sopenharmony_ci{
11006f6ba60Sopenharmony_ci    if (shareMemoryBlock_ == nullptr) {
11106f6ba60Sopenharmony_ci        return;
11206f6ba60Sopenharmony_ci    }
11306f6ba60Sopenharmony_ci
11406f6ba60Sopenharmony_ci    profilerPluginData_.finishAdd_data(size);
11506f6ba60Sopenharmony_ci    struct timespec ts;
11606f6ba60Sopenharmony_ci    clock_gettime(CLOCK_REALTIME, &ts);
11706f6ba60Sopenharmony_ci    profilerPluginData_.set_clock_id(ProfilerPluginData::CLOCKID_REALTIME);
11806f6ba60Sopenharmony_ci    profilerPluginData_.set_tv_sec(ts.tv_sec);
11906f6ba60Sopenharmony_ci    profilerPluginData_.set_tv_nsec(ts.tv_nsec);
12006f6ba60Sopenharmony_ci    int32_t len = profilerPluginData_.Finish();
12106f6ba60Sopenharmony_ci    shareMemoryBlock_->UseMemory(len);
12206f6ba60Sopenharmony_ci    DoStats(len);
12306f6ba60Sopenharmony_ci}
12406f6ba60Sopenharmony_ci
12506f6ba60Sopenharmony_cibool BufferWriter::WriteMessage(const google::protobuf::Message& pmsg, const std::string& pluginName)
12606f6ba60Sopenharmony_ci{
12706f6ba60Sopenharmony_ci    if (shareMemoryBlock_ == nullptr) {
12806f6ba60Sopenharmony_ci        return false;
12906f6ba60Sopenharmony_ci    }
13006f6ba60Sopenharmony_ci    DoStats(pmsg.ByteSizeLong());
13106f6ba60Sopenharmony_ci    return shareMemoryBlock_->PutMessage(pmsg, pluginName);
13206f6ba60Sopenharmony_ci}
13306f6ba60Sopenharmony_ci
13406f6ba60Sopenharmony_cibool BufferWriter::Flush()
13506f6ba60Sopenharmony_ci{
13606f6ba60Sopenharmony_ci    ++flushCount_;
13706f6ba60Sopenharmony_ci    if (eventNotifier_ == nullptr) {
13806f6ba60Sopenharmony_ci        return false;
13906f6ba60Sopenharmony_ci    }
14006f6ba60Sopenharmony_ci    eventNotifier_->Post(flushCount_.load());
14106f6ba60Sopenharmony_ci    lastFlushTime_ = std::chrono::steady_clock::now();
14206f6ba60Sopenharmony_ci    bytesPending_ = 0;
14306f6ba60Sopenharmony_ci    return true;
14406f6ba60Sopenharmony_ci}
14506f6ba60Sopenharmony_ci
14606f6ba60Sopenharmony_civoid BufferWriter::UseMemory(int32_t size)
14706f6ba60Sopenharmony_ci{
14806f6ba60Sopenharmony_ci    if (shareMemoryBlock_ == nullptr) {
14906f6ba60Sopenharmony_ci        return;
15006f6ba60Sopenharmony_ci    }
15106f6ba60Sopenharmony_ci
15206f6ba60Sopenharmony_ci    shareMemoryBlock_->UseMemory(size);
15306f6ba60Sopenharmony_ci    DoStats(size);
15406f6ba60Sopenharmony_ci}
15506f6ba60Sopenharmony_ci
15606f6ba60Sopenharmony_civoid BufferWriter::ResetPos()
15706f6ba60Sopenharmony_ci{
15806f6ba60Sopenharmony_ci    if (shareMemoryBlock_ == nullptr) {
15906f6ba60Sopenharmony_ci        return;
16006f6ba60Sopenharmony_ci    }
16106f6ba60Sopenharmony_ci
16206f6ba60Sopenharmony_ci    shareMemoryBlock_->ResetPos();
16306f6ba60Sopenharmony_ci}