文件系統核心存儲引擎_實現(三)

文件映射操作類頭文件定義

在這裏插入圖片描述

#ifndef QINIU_LARGEFILE_MMAPFILE_OP_H_
#define QINIU_LARGEFILE_MMAPFILE_OP_H_

#include "common.h"
#include "file_op.h"
#include "mmap_file.h"

namespace qiniu
{
    namespace largefile
    {
        class MMapFileOperation : public FileOperation
        {
            public:
            MMapFileOperation(const std::string& file_name, const int open_flags = O_CREAT | O_RDWR | O_LARGEFILE):
            FileOperation(file_name, open_flags), map_file_(NULL), is_mapped_(false)
            {

            }


            ~MMapFileOperation()
            {
                if (map_file_)
                {
                    delete(map_file_);
                    map_file_ = NULL;
                }
            }


            int pread_file(char *buf, const int32_t size, const int64_t, offset);
            int pwrite_file(const char* buf, const int32_t sized, const int64_t offset);

            int mmap_file(const MMapOption &mmap_option);
            int munmap_file();

            void *get_map_data() const;
            int flush_file();

            private:
            MMapFile *map_file_;
            bool is_mapped_;
        }

    }
}

#endif /* QINIU_LARGEFILE_MMAPFILE_OP_H_ */

文件映射操作類CPP實現

在這裏插入圖片描述

#include "mmap_file_op.h"
#include "common.h"

static int debug = 1;

namespace qiniu
{
    namespace largefile
    {
        int MMapFileOperation::mmap_file(const MMapOption &mmap_option)
        {
            if (mmap_option.max_mmap_size_ < mmap_option.first_mmap_size_)
            {
                return TFS_ERROR;
            }

            if (mmap_option.max_mmap_size_ <= 0)
            {
                return TFS_ERROR;
            }

            int fd = check_file();
            if (fd < 0)
            {
                fprintf(stderr, "MMapFileOperation::mmap_file-checking file failed!");
                return TFS_ERROR;
            }

            if (!is_mapped_)
            {
                if (map_file_)
                {
                    delete(map_file_);
                }
                map_file_ = new MMapFile(mmap_option, fd);
                is_mapped_ = map_file_->map_file(true);
            }

            if (is_mapped_)
            {
                return TFS_SUCCESS;
            }
            else
            {
                return TFS_ERROR;
            }
        }


        int MMapFileOperation::munmap_file()
        {
            if (is_mapped_ && map_file_ != NULL)
            {
                delete(map_file_);
                is_mapped_ = false;
            }

            return TFS_SUCCESS;
        }


        void *MMapFileOperation::get_map_data() const
        {
            if (is_mapped_)
            {
                return map_file_->get_data();
            }

            return NULL;
        }


        int MMapFileOperation::pread_file(char *buf, const int32_t size, const int64_t, offset)
        {
            /* 情況1: 內存已經映射 */
            if (is_mapped_ && (offset + size) > map_file_->get_size())
            {
                if (debug)
                {
                    fprintf(stdout, "MMapFileOperation: pread, size: %d, offset: %"__PRI64_PREFIX"d, map file size: %d: need remap\n",
                    size, offset, map_file_->get_size());
                    map_file_->remap_file();
                }
            }

            if (is_mapped_ && (offset + size) <= map_file_->get_size())
            {
                memcpy(buf, (char *)map_file_->get_data + offset, size);
                return TFS_SUCCESS;
            }

            /* 情況2: 內存沒有映射 */
            return FileOperation::pread_file(buf, size, offset);
        }


        int MMapFileOperation::pwrite_file(const char* buf, const int32_t sized, const int64_t offset)
        {
            /* 情況1: 內存已經映射 */
            if (is_mapped_ && (offset + size) > map_file_->get_size())
            {
                if (debug)
                {
                    fprintf(stdout, "MMapFileOperation: pwrite, size: %d, offset: %"__PRI64_PREFIX"d, map file size: %d: need remap\n",
                    size, offset, map_file_->get_size());
                    map_file_->remap_file();
                }
            }

            if (is_mapped_ && (offset + size) <= map_file_->get_size())
            {
                memcpy((char*)map_file_->get_data()+offset, buf, size);
                return TFS_SUCCESS;
            }

            /* 情況2: 內存沒有映射或是要寫入的數據映射不全 */
            return FileOperation::pwrite_file(buf, size, offset);
        }


        int MMapFileOperation::flush_file()
        {
            if (is_mapped_)
            {
                if (map_file_->sync_file())
                {
                    return TFS_SUCCESS;
                }
                else
                {
                    return TFS_ERROR;
                }
            }

            return FileOperation::flush_file();
        }
    }
}

在這裏插入圖片描述

#ifndef _COMMON_H_INCLUDED_
#define _COMMON_H_INCLUDED_

#include <iostream>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdlib.h>

namespace qiniu
{
    namespace largefile
    {
        const int32_t TFS_SUCCESS = 0;
        const int32_t TFS_ERROR = -1;
        const int32_t EXIT_DISK_OPER_INCOMPLETE = -8012; /* read or write length is less than required */
    }
}

#endif /* _COMMON_H_INCLUDED_ */

文件映射操作類單元測試 (一)

在這裏插入圖片描述

#include "mmap_file_op.h"
#include <iostream>

using namespace std;
using namespace qiniu;

const static largefile::MMapOption mmap_option = {10240000, 4096, 4096}; /* 內存映射的參數 */

int main(void)
{
    int ret = 0;
    const char *filename = "mmap_file_op.txt";
    largefile::MMapFileOperation *mmfo = new largefile::MMapFileOperation(filename);

    int fd = mmfo->open_file();
    if (fd < 0)
    {
        fprintf(stderr, "open file %s failed reason: %s\n", filename, strerror(-fd));
        exit(-1);
    }

    ret = mmfo->mmap_file(mmap_option);
    if (ret == largefile::TFS_ERROR)
    {
        fprintf(stderr, "mmap_file reason: %s\n", strerror(errno));
        mmfo->close_file();
        exit(-2);
    }

    char buffer[128+1];
    memset(buffer, '6', 128);

    ret = mmfo->pwrite_file(buffer, 128, 8);
    if (ret < 0)
    {
        if (ret == largefile::EXIT_DISK_OPER_INCOMPLETE)
        {
            fprintf(stderr, "pwrite_file: read length is less than required!\n");
        }
        else
        {
            fprintf(stderr, "pWrite_file %s failed reason: %s\n", filename, strerror(-ret));
        }
    }

    memset(buffer, 0, 128);
    ret = mmfo->pread_file(buffer, 128, 8);
    if (ret < 0)
    {
        if (ret == largefile::EXIT_DISK_OPER_INCOMPLETE)
        {
            fprintf(stderr, "pread_file length is less than required!");
        }
        else
        {
            fprintf(stderr, "pread_file %s failed reason: %s\n", filename, strerror(-ret));
        }
    }
    else
    {
        buffer[128] = '\0';
        printf("read: %s\n", buffer);
    }

    ret = mmfo->flush_file();
    if (ret == largefile::TFS_ERROR)
    {
        fprintf(stderr, "flush file failed. reason: %s \n", strerror(errno));
    }

    mmfo->munmap_file();

    mmfo->close_file();
    

    return 0;
}

編譯:

g++ file_op.cpp mmap_file_op.cpp mmap_file_op_test.cpp mmap_file.cpp -o mmap_file_op_test

執行:

在這裏插入圖片描述
在這裏插入圖片描述

文件映射操作類單元測試 (二)

在這裏插入圖片描述

#include "mmap_file_op.h"
#include <iostream>

using namespace std;
using namespace qiniu;

const static largefile::MMapOption mmap_option = {10240000, 4096, 4096}; /* 內存映射的參數 */

int main(void)
{
    int ret = 0;
    const char *filename = "mmap_file_op.txt";
    largefile::MMapFileOperation *mmfo = new largefile::MMapFileOperation(filename);

    int fd = mmfo->open_file();
    if (fd < 0)
    {
        fprintf(stderr, "open file %s failed reason: %s\n", filename, strerror(-fd));
        exit(-1);
    }

    ret = mmfo->mmap_file(mmap_option);
    if (ret == largefile::TFS_ERROR)
    {
        fprintf(stderr, "mmap_file reason: %s\n", strerror(errno));
        mmfo->close_file();
        exit(-2);
    }

    char buffer[128+1];
    memset(buffer, '6', 128);
    buffer[127] = '\n';

    ret = mmfo->pwrite_file(buffer, 128, 8);
    if (ret < 0)
    {
        if (ret == largefile::EXIT_DISK_OPER_INCOMPLETE)
        {
            fprintf(stderr, "pwrite_file: read length is less than required!\n");
        }
        else
        {
            fprintf(stderr, "pWrite_file %s failed reason: %s\n", filename, strerror(-ret));
        }
    }

    memset(buffer, 0, 128);
    ret = mmfo->pread_file(buffer, 128, 8);
    if (ret < 0)
    {
        if (ret == largefile::EXIT_DISK_OPER_INCOMPLETE)
        {
            fprintf(stderr, "pread_file length is less than required!");
        }
        else
        {
            fprintf(stderr, "pread_file %s failed reason: %s\n", filename, strerror(-ret));
        }
    }
    else
    {
        buffer[128] = '\0';
        printf("read: %s\n", buffer);
    }

    ret = mmfo->flush_file();
    if (ret == largefile::TFS_ERROR)
    {
        fprintf(stderr, "flush file failed. reason: %s \n", strerror(errno));
    }

    memset(buffer, '8', 128);
    buffer[127] = '\n';
    ret = mmfo->pwrite_file(buffer, 128, 4000);

    mmfo->munmap_file();

    mmfo->close_file();
    

    return 0;
}

編譯:

g++ file_op.cpp mmap_file_op.cpp mmap_file_op_test.cpp mmap_file.cpp -o mmap_file_op_test

執行:

在這裏插入圖片描述

結語:

時間: 2020-06-24

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章