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

內存映射實戰之文件操作父類頭文件定義

在這裏插入圖片描述

#ifndef QINIU_LARGE_FILE_OP_H_
#define QINIU_LARGE_FILE_OP_H_

#include "common.h"

namespace qiniu
{
    namespace largefile
    {
        class FileOperation
        {
            public:
            FileOperation(const std::string &file_name, const int open_fags = O_RDWR | O_LARGEFILE);
            ~FileOperation();

            int open_file();
            void close_file();

            int flush_file(); /* 把文件立即寫入到磁盤 */

            int unlink_file();

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

            int write_file(const char *buf, const int32_t nbytes);

            int64_t get_file_size();

            int ftruncate_file(const int64_t length);
            int seek_file(const int64_t offset);

            int get_fd() const
            {
                return fd_;
            }

            protected:
            int fd_;
            int open_fags_;
            char *file_name_;

            protected:
            int check_file();

            protected:
            static const mode_t OPEN_MODE = 0644; /* 0: 八進制 */
            static const int MAX_DISK_TIMES = 5;
        };
    }
}
#endif /* */

內存映射實戰之文件操作CPP實現(上)

在這裏插入圖片描述

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

namespace qiniu
{
    namespace largefile
    {
        FileOperation::FileOperation(const std::string &file_name, const int open_fags):
        fd_(-1), open_fags_(open_fags)
        {
            file_name_ = strdup(file_name.c_str()); /* strdup() 動態內存分配記得要釋放 */
        }

        FileOperation::~FileOperation()
        {
            if (fd_ > 0)
            {
                ::close(fd_);
            }

            if (NULL != file_name_)
            {
                free(file_name_); /* 釋放第11行strdup()的動態內存分配 */
                file_name_ = NULL;
            }
        }

        int FileOperation::open_file()
        {
            if (fd_ > 0)
            {
                close(fd_);
                fd_ = -1;
            }

            fd_ = ::open(file_name_, open_fags_, OPEN_MODE);
            if (fd_ < 0)
            {
                return -errno;
            }

            return fd_;
        }

        void FileOperation::close_file()
        {
            if (fd_ < 0)
            {
                return;
            }

            ::close(fd_);
            fd_ = -1;
        }

        int64_t FileOperation::get_file_size() /* 獲取文件的大小 */
        {
            int fd = check_file();

            if (fd < 0)
            {
                return -1;
            }

            struct stat statbuf;
            if (fstat(fd, &statbuf) != 0)
            {
                return -1;
            }

            return statbuf.st_size;
        }

        int FileOperation::check_file()
        {
            if (fd_ < 0)
            {
                fd_ = open_file();
            }

            return fd_;
        }

        int FileOperation::ftruncate_file(const int64_t length)
        {
            int fd = check_file();

            if (fd < 0)
            {
                return -fd;
            }

            return ftruncate(fd, length);
        }

        int FileOperation::seek_file(const int64_t offset)
        {
            int fd = check_file();

            if (fd < 0)
            {
                return fd;
            }

            return lseek(fd, offset, SEEK_SET);
        }

        int FileOperation::flush_file() /* 把文件立即寫入到磁盤 */
        {
            if (open_fags_ & O_SYNC) /* O_SYNC 同步 */
            {
                return 0;
            }

            int fd = check_file();
            if (fd < 0)
            {
                return fd;
            }

            return fsync(fd);
        }

        int FileOperation::unlink_file()
        {
            close_file();
            return ::unlink(file_name_);
        }

        int FileOperation::pread_file(char *buf, const int32_t nbytes, const int64_t offset)
        {
            int32_t left = nbytes;
            int64_t read_offset = offset;
            int32_t read_len = 0;
            char *p_tmp = buf;

            int i = 0;

            while (left > 0)
            {
                ++i;

                if (i >= MAX_DISK_TIMES)
                {
                    break;
                }

                if (check_file() < 0)
                {
                    return -errno;
                }

                read_len = ::pread64(fd_, p_tmp, left, read_offset);

                if (read_len < 0)
                {
                    read_len = -errno;

                    if (-read_len == EINTR || EAGAIN == -read_len)
                    {
                        continue;
                    }
                    else if (EBADF == -read_len)
                    {
                        fd_ = -1;
                        continue;
                    }
                    else if (EBADF == -read_len)
                    {
                        fd_ = -1;
                        return read_len;
                    }else
                    {
                        return read_len;
                    }
                }
                else if (0 == read_len)
                {
                    break;
                }
                left -= read_len;
                p_tmp += read_len;
                read_offset += read_len;

                if (0 != left)
                {
                    return EXIT_DISK_OPER_INCOMPLETE;
                }

                return TFS_SUCCESS;
            }  
        }

        int FileOperation::pwrite_file(const char *buf, const int32_t nbytes, const int64_t offset)
        {
            int32_t left = nbytes;
            int64_t write_offset = offset;
            int32_t written_len = 0;
            const char *p_tmp = buf;

            int i = 0;

            while (left > 0)
            {
                ++i;

                if (i >= MAX_DISK_TIMES)
                {
                    break;
                }

                if (check_file() < 0)
                {
                    return -errno;
                }

                written_len = ::pwrite64(fd_, p_tmp, left, write_offset);

                if (written_len < 0)
                {
                    written_len = -errno;

                    if (-written_len == EINTR || EAGAIN == -written_len)
                    {
                        continue;
                    }
                    else if (EBADF == -written_len)
                    {
                        fd_ = -1;
                        continue;
                    }
                    else
                    {
                        return written_len;
                    } 
                }
                else if (0 == written_len)
                {
                    break;
                }

                left -= written_len;
                p_tmp += written_len;
                write_offset += written_len;

                if (0 != left)
                {
                    return EXIT_DISK_OPER_INCOMPLETE;
                }

                return TFS_SUCCESS;
            }  
        }

        int FileOperation::write_file(const char *buf, const int32_t nbytes)
        {
            int32_t left = nbytes;
            int32_t written_len = 0;
            const char *p_tmp = buf;

            int i = 0;

            while (left > 0)
            {
                ++i;

                if (i >= MAX_DISK_TIMES)
                {
                    break;
                }

                if (check_file() < 0)
                {
                    return -errno;
                }

                written_len = ::write(fd_, p_tmp, left);

                if (written_len < 0)
                {
                    written_len = -errno;

                    if (-written_len == EINTR || EAGAIN == -written_len)
                    {
                        continue;
                    }
                    else if (EBADF == -written_len)
                    {
                        fd_ = -1;
                        return written_len;
                    }
                    else
                    {
                        return written_len;
                    }   
                }
                else if (0 == written_len)
                {
                    break;
                }

                left -= written_len;
                p_tmp += written_len;
            }
        }
    }
}

內存映射實戰之文件操作CPP實現(中)

在這裏插入圖片描述

#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 EXIT_DISK_OPER_INCOMPLETE = -8012; /* read or write length is less than required */
    }
}

#endif /* _COMMON_H_INCLUDED_ */

在這裏插入圖片描述

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

using namespace std;
using namespace qiniu;

int main(void)
{
    const char *filename = "file_op.txt";
    largefile::FileOperation *fileOP = new largefile::FileOperation(filename, O_CREAT | O_RDWR | O_LARGEFILE);

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

    char buffer[4096];
    memset(buffer, '6', 4096);
    int ret = fileOP->pwrite_file(buffer, 4096, 1024);
    if (ret < 0)
    {
        fprintf(stderr, "pwrite file %s failed reason: %s\n", filename, strerror(-ret));
    }

    fileOP->close_file();

    return 0;
}

demo(一)測試運行結果:

在這裏插入圖片描述

more file_op.txt

在這裏插入圖片描述

demo(二)測試運行結果:

在這裏插入圖片描述

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

using namespace std;
using namespace qiniu;

int main(void)
{
    const char *filename = "file_op.txt";
    largefile::FileOperation *fileOP = new largefile::FileOperation(filename, O_CREAT | O_RDWR | O_LARGEFILE);

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

    char buffer[64+1];
    memset(buffer, '8', 64);
    int ret = fileOP->pwrite_file(buffer, 64, 1024);
    if (ret < 0)
    {
        fprintf(stderr, "pwrite file %s failed reason: %s\n", filename, strerror(-ret));
    }

    memset(buffer, 0, 64);
    ret = fileOP->pread_file(buffer, 64, 1024);
    if (ret < 0)
    {
        fprintf(stderr, "pread file %s failed reason %s \n", filename, strerror(-ret));
    }
    else
    {
        buffer[64] = '\0';
        printf("read: %s \n", buffer);
    }
    

    fileOP->close_file();

    return 0;
}

運行結果:
在這裏插入圖片描述

demo(三)測試運行結果:

在這裏插入圖片描述

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

using namespace std;
using namespace qiniu;

int main(void)
{
    const char *filename = "file_op.txt";
    largefile::FileOperation *fileOP = new largefile::FileOperation(filename, O_CREAT | O_RDWR | O_LARGEFILE);

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


    char buffer[64+1];
    memset(buffer, '8', 64);
    int ret = fileOP->pwrite_file(buffer, 64, 1024);
    if (ret < 0)
    {
        if (ret == largefile::EXIT_DISK_OPER_INCOMPLETE)
        {
            fprintf(stderr, "pwrite_file: read length is less than required!");
        }
        else
        {
            fprintf(stderr, "pwrite file %s failed reason: %s\n", filename, strerror(-ret));
        } 
    }


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


    memset(buffer, '9', 64);
    ret = fileOP->write_file(buffer, 64);
    if (ret < 0)
    {
        if (ret == largefile::EXIT_DISK_OPER_INCOMPLETE)
        {
            fprintf(stderr, "write_file: read length is less than requirend!");
        }
        else
        {
            fprintf(stderr, "write_file %s failed reason: %s\n", filename, strerror(-ret));
        }
    }
    

    fileOP->close_file();

    return 0;
}

運行結果:

在這裏插入圖片描述

more file_op.txt

在這裏插入圖片描述

總結:

文件的指針不變, 因此插入的字符, 還是在頭部開始

demo(四)測試運行結果:

在這裏插入圖片描述

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

using namespace std;
using namespace qiniu;

int main(void)
{
    const char *filename = "file_op.txt";
    largefile::FileOperation *fileOP = new largefile::FileOperation(filename, O_CREAT | O_RDWR | O_LARGEFILE);

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


    char buffer[64+1];
    memset(buffer, '8', 64);
    int ret = fileOP->pwrite_file(buffer, 64, 128);
    if (ret < 0)
    {
        if (ret == largefile::EXIT_DISK_OPER_INCOMPLETE)
        {
            fprintf(stderr, "pwrite_file: read length is less than required!");
        }
        else
        {
            fprintf(stderr, "pwrite file %s failed reason: %s\n", filename, strerror(-ret));
        } 
    }


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


    memset(buffer, '9', 64);
    ret = fileOP->write_file(buffer, 64);
    if (ret < 0)
    {
        if (ret == largefile::EXIT_DISK_OPER_INCOMPLETE)
        {
            fprintf(stderr, "write_file: read length is less than requirend!");
        }
        else
        {
            fprintf(stderr, "write_file %s failed reason: %s\n", filename, strerror(-ret));
        }
    }
    

    fileOP->close_file();

    return 0;
}

運行結果:
在這裏插入圖片描述

vi file_op.tx

在這裏插入圖片描述

總結:

文件的指針不變, 因此插入的字符, 還是在頭部開始

結語:

溫馨提示: 請不要用跑步鞋和在有太陽的情況下打球, 打球, 容易扭傷, 我星期五的時候打球(好久沒有和舍友打球, 拉這他們打, 外面太陽溫度有點大, 因爲溫度太高, 所以沒有打超過30分鐘, 沒勁.)

時間: 2020-06-20

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