提交 847b931a 编写于 作者: L liuqi

Refactor file storage to use native file apis.

上级 6c33224a
...@@ -4,10 +4,17 @@ ...@@ -4,10 +4,17 @@
#include "mace/core/file_storage.h" #include "mace/core/file_storage.h"
#include <fstream> #include <fcntl.h>
#include <limits.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <algorithm>
#include <memory> #include <memory>
#include <utility> #include <utility>
#include "mace/utils/logging.h" #include "mace/utils/logging.h"
namespace mace { namespace mace {
...@@ -43,28 +50,66 @@ FileStorage::FileStorage(const std::string &file_path): ...@@ -43,28 +50,66 @@ FileStorage::FileStorage(const std::string &file_path):
file_path_(file_path) {} file_path_(file_path) {}
void FileStorage::Load() { void FileStorage::Load() {
std::ifstream ifs(file_path_, std::ios::binary | std::ios::in); struct stat st;
if (ifs.is_open()) { stat(file_path_.c_str(), &st);
int64_t data_size = 0; size_t file_size = st.st_size;
ifs.read(reinterpret_cast<char *>(&data_size), sizeof(data_size)); int fd = open(file_path_.c_str(), O_RDONLY);
while (data_size--) { if (fd == -1) {
int32_t key_size = 0; LOG(WARNING) << "open file " << file_path_
ifs.read(reinterpret_cast<char *>(&key_size), sizeof(key_size)); << " failed, error code: " << errno;
std::string key(key_size, ' '); return;
ifs.read(&key[0], key_size); }
unsigned char *file_data =
int32_t value_size = 0; static_cast<unsigned char *>(mmap(nullptr, file_size, PROT_READ,
ifs.read(reinterpret_cast<char *>(&value_size), MAP_PRIVATE, fd, 0));
sizeof(value_size)); int res = 0;
if (file_data == MAP_FAILED) {
std::vector<unsigned char> value(value_size); LOG(WARNING) << "mmap file " << file_path_
ifs.read(reinterpret_cast<char *>(value.data()), << " failed, error code: " << errno;
value_size);
data_.emplace(key, value); res = close(fd);
if (res != 0) {
LOG(WARNING) << "close file " << file_path_
<< " failed, error code: " << errno;
} }
ifs.close(); return;
} else { }
LOG(INFO) << "No file to Read."; unsigned char *file_data_ptr = file_data;
const size_t int_size = sizeof(int32_t);
int64_t data_size = 0;
memcpy(&data_size, file_data_ptr, sizeof(int64_t));
file_data_ptr += sizeof(int64_t);
int32_t key_size = 0;
int32_t value_size = 0;
for (int i = 0; i < data_size; ++i) {
memcpy(&key_size, file_data_ptr, int_size);
file_data_ptr += int_size;
std::unique_ptr<char[]> key(new char[key_size+1]);
memcpy(&key[0], file_data_ptr, key_size);
file_data_ptr += key_size;
key[key_size] = '\0';
memcpy(&value_size, file_data_ptr, int_size);
file_data_ptr += int_size;
std::vector<unsigned char> value(value_size);
memcpy(value.data(), file_data_ptr, value_size);
file_data_ptr += value_size;
data_.emplace(std::string(&key[0]), value);
}
res = munmap(file_data, file_size);
if (res != 0) {
LOG(WARNING) << "munmap file " << file_path_
<< " failed, error code: " << errno;
return;
}
res = close(fd);
if (res != 0) {
LOG(WARNING) << "close file " << file_path_
<< " failed, error code: " << errno;
} }
} }
...@@ -82,26 +127,59 @@ std::vector<unsigned char> *FileStorage::Find(const std::string &key) { ...@@ -82,26 +127,59 @@ std::vector<unsigned char> *FileStorage::Find(const std::string &key) {
} }
void FileStorage::Flush() { void FileStorage::Flush() {
std::ofstream ofs(file_path_, int fd = open(file_path_.c_str(), O_WRONLY | O_CREAT, 0600);
std::ios::binary | std::ios::out); if (fd < 0) {
if (ofs.is_open()) { LOG(WARNING) << "open file " << file_path_
int64_t data_size = data_.size(); << " failed, error code:" << errno;
ofs.write(reinterpret_cast<const char *>(&data_size), return;
sizeof(data_size)); }
for (auto &kv : data_) {
int32_t key_size = static_cast<int32_t>(kv.first.size()); const size_t int_size = sizeof(int32_t);
ofs.write(reinterpret_cast<const char *>(&key_size), sizeof(key_size));
ofs.write(kv.first.c_str(), key_size); int64_t data_size = sizeof(int64_t);
for (auto &kv : data_) {
int32_t value_size = static_cast<int32_t>(kv.second.size()); data_size += 2 * int_size + kv.first.size() + kv.second.size();
ofs.write(reinterpret_cast<const char *>(&value_size), }
sizeof(value_size)); std::unique_ptr<unsigned char[]> buffer(new unsigned char[data_size]);
ofs.write(reinterpret_cast<const char*>(kv.second.data()), unsigned char *buffer_ptr = &buffer[0];
value_size);
int64_t num_of_data = data_.size();
memcpy(buffer_ptr, &num_of_data, sizeof(int64_t));
buffer_ptr += sizeof(int64_t);
for (auto &kv : data_) {
int32_t key_size = kv.first.size();
memcpy(buffer_ptr, &key_size, int_size);
buffer_ptr += int_size;
memcpy(buffer_ptr, kv.first.c_str(), kv.first.size());
buffer_ptr += kv.first.size();
int32_t value_size = kv.second.size();
memcpy(buffer_ptr, &value_size, int_size);
buffer_ptr += int_size;
memcpy(buffer_ptr, kv.second.data(), kv.second.size());
buffer_ptr += kv.second.size();
}
int res = 0;
buffer_ptr = &buffer[0];
int64_t remain_size = data_size;
while (remain_size > 0) {
size_t buffer_size = std::min<int64_t>(remain_size, SSIZE_MAX);
res = write(fd, buffer_ptr, buffer_size);
if (res == -1) {
LOG(WARNING) << "write file " << file_path_
<< " failed, error code: " << errno;
return;
} }
ofs.close(); remain_size -= buffer_size;
} else { buffer_ptr += buffer_size;
LOG(WARNING) << "Write failed, please check directory exists"; }
res = close(fd);
if (res != 0) {
LOG(WARNING) << "close file " << file_path_
<< " failed, error code: " << errno;
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册