baidu/braft

handle error in ProtoBufFile::load

CkTD opened this issue · 0 comments

CkTD commented

int ProtoBufFile::load(google::protobuf::Message* message) {
butil::File::Error e;
FileAdaptor* file = _fs->open(_path, O_RDONLY, NULL, &e);
if (!file) {
LOG(WARNING) << "open file failed, path: " << _path
<< ": " << butil::File::ErrorToString(e);
return -1;
}
std::unique_ptr<FileAdaptor, DestroyObj<FileAdaptor> > guard(file);
// len
butil::IOPortal header_buf;
if (sizeof(int32_t) != file->read(&header_buf, 0, sizeof(int32_t))) {
LOG(WARNING) << "read len failed, path: " << _path;
return -1;
}
int32_t len = 0;
header_buf.copy_to(&len, sizeof(int32_t));
int32_t left_len = butil::NetToHost32(len);
// read protobuf data
butil::IOPortal msg_buf;
if (left_len != file->read(&msg_buf, sizeof(int32_t), left_len)) {
LOG(WARNING) << "read body failed, path: " << _path;
return -1;
}
// parse msg
butil::IOBufAsZeroCopyInputStream msg_wrapper(msg_buf);
message->ParseFromZeroCopyStream(&msg_wrapper);
return 0;
}

  1. 117 行没有检查返回值
  2. 如果执行到了112行, 且原因是实际文件长度比预期的短,返回了 -1。但读文件是成功的,errno 不会被更新。加载 log_meta时,如果发生了上述问题,且原来的 errno 正好是 ENOENT,后续逻辑会认为日志是空的,直接把 log 删光。

braft/src/braft/log.cpp

Lines 1155 to 1175 in e32b78a

int SegmentLogStorage::load_meta() {
butil::Timer timer;
timer.start();
std::string meta_path(_path);
meta_path.append("/" BRAFT_SEGMENT_META_FILE);
ProtoBufFile pb_file(meta_path);
LogPBMeta meta;
if (0 != pb_file.load(&meta)) {
PLOG_IF(ERROR, errno != ENOENT) << "Fail to load meta from " << meta_path;
return -1;
}
_first_log_index.store(meta.first_log_index());
timer.stop();
LOG(INFO) << "log load_meta " << meta_path << " first_log_index: " << meta.first_log_index()
<< " time: " << timer.u_elapsed();
return 0;
}