112d44d9创建于 2023年8月14日历史提交
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
 * 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 HIEBPF_DATA_FILE_H
#define HIEBPF_DATA_FILE_H
#include <sys/mman.h>
#include <cerrno>
#include <memory>
#include <string>
#include <mutex>

#include <fcntl.h>
#include <unistd.h>

#include "type_headers.h"
#include "ringbuffer.h"
#include "hhlog.h"


struct DataFileHeader {
    enum HeaderConsts:std::size_t {
        MAGIC_LEN = 8,
        TOTAL_HEAD_SIZE = 1024,
        FIXED_HEAD_SIZE = 24
    };
    char magic[MAGIC_LEN] = {'E', 'B', 'P', 'F', 'F', 'I', 'L', 'E'};
    __u32 headSize_ {TOTAL_HEAD_SIZE};
    __u32 version_ {0};
    __u32 clock_ {1};
    __u32 cmdLen_ {0};
    char cmd_[TOTAL_HEAD_SIZE - FIXED_HEAD_SIZE] {};
};

class HiebpfDataFile {
public:
    ~HiebpfDataFile()
    {
        if (mapAddr_) {
            munmap(mapAddr_, length_);
            mapAddr_ = nullptr;
        }
        if (fd_ != -1) {
            std::size_t curPos = mapPos_ + offset_;
            ftruncate(fd_, curPos);
            close(fd_);
            fd_ = -1;
        }
    }

    static std::shared_ptr<HiebpfDataFile> MakeShared(
        const std::string& cmd,
        const std::string& filename,
        const std::size_t pages = DEFAULT_MMAP_PAGES);
    void* Reserve(const std::size_t size);
    void Discard(void *data);
    void Submit(void *data);
    void WriteKernelSymbol();

    enum Constants:std::size_t {
        DEFAULT_MMAP_PAGES = (1 << 8),
        DEFAULT_MMAP_LENGTH = (1 << 20),
        DEFAULT_PAGE_SIZE = (1 << 12),
    };

private:
    int MapFile();
    int RemapFile(const std::size_t size);
    HiebpfDataFile(
        const std::string& cmd,
        const std::string& filename,
        const std::size_t pages = DEFAULT_MMAP_PAGES)
        : hiebpfCmd_ {cmd},
          filename_ {filename}
    {
        long pageSize = sysconf(_SC_PAGE_SIZE);
        HHLOGI(true, "page size of the current OS: %u bytes", pageSize);
        if (pageSize > 0) {
            pageSize_ = static_cast<size_t>(pageSize);
            length_ = static_cast<size_t>(pageSize * pages);
        }
        HHLOGI(true, "mmap length = %u", length_);
    }

    inline int OpenFile()
    {
        constexpr int FILE_MODE = 0644;
        fd_ = open(filename_.c_str(), O_RDWR | O_CREAT, FILE_MODE);
        return (fd_ < 0) ? -1 : 0;
    }

    inline int ExtendFile(const std::size_t mapPos, const std::size_t mapLength)
    {
        if (ftruncate(fd_, mapPos + mapLength) != 0) {
            HHLOGE(true, "failed to extend data file");
            return -1;
        }
        return 0;
    }

    int WriteFileHeader()
    {
        struct DataFileHeader header {};
        header.cmdLen_ = hiebpfCmd_.length() + 1;
        if (strncpy_s(header.cmd_, header.TOTAL_HEAD_SIZE - header.FIXED_HEAD_SIZE,
                      hiebpfCmd_.c_str(), hiebpfCmd_.length() + 1) != EOK) {
            HHLOGE(true, "failed to copy string");
            return -1;
        }
        if (memcpy_s(mapAddr_, length_, &header, sizeof(header)) != EOK) {
            HHLOGE(true, "failed to memcpy_s");
            return -1;
        }
        offset_ += sizeof(header);
        return 0;
    }

    const std::string hiebpfCmd_ {};
    const std::string filename_ {"/data/local/tmp/hiebpf.data"};
    std::size_t length_ {DEFAULT_MMAP_LENGTH};
    std::size_t pageSize_ {};

    int fd_ {-1};
    void *mapAddr_ {MAP_FAILED};
    std::size_t mapPos_ {0};
    std::size_t offset_ {0};
    std::mutex mtx_ {};
};

#endif