文件映射操作类头文件定义
#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