Add real_size to Stat.

GitOrigin-RevId: 3b8b4c24504ed1fa7eed1885abd3a3e9014eb2c4
This commit is contained in:
levlam 2020-01-03 01:01:39 +03:00
parent 12ab53bdfa
commit 69f30a3505
5 changed files with 32 additions and 0 deletions

View File

@ -480,6 +480,11 @@ Result<int64> FileFd::get_size() const {
return s.size_;
}
Result<int64> FileFd::get_real_size() const {
TRY_RESULT(s, stat());
return s.real_size_;
}
#if TD_PORT_WINDOWS
static uint64 filetime_to_unix_time_nsec(LONGLONG filetime) {
const auto FILETIME_UNIX_TIME_DIFF = 116444736000000000ll;
@ -510,6 +515,11 @@ Result<Stat> FileFd::stat() const {
return OS_ERROR("Get FileStandardInfo failed");
}
res.size_ = standard_info.EndOfFile.QuadPart;
res.real_size_ = standard_info.AllocationSize.QuadPart;
if (res.size_ != 0 && res.real_size_ <= 0 ) {
res.real_size_ = res.size_; // just in case
}
return res;
#endif

View File

@ -50,11 +50,15 @@ class FileFd {
PollableFdInfo &get_poll_info();
const PollableFdInfo &get_poll_info() const;
void close();
bool empty() const;
Result<int64> get_size() const;
Result<int64> get_real_size() const;
Result<Stat> stat() const;
Status sync() TD_WARN_UNUSED_RESULT;

View File

@ -106,6 +106,7 @@ Stat from_native_stat(const struct ::stat &buf) {
res.atime_nsec_ = static_cast<uint64>(buf.st_atime) * 1000000000 + time_nsec.first;
res.mtime_nsec_ = static_cast<uint64>(buf.st_mtime) * 1000000000 + time_nsec.second / 1000 * 1000;
res.size_ = buf.st_size;
res.real_size_ = buf.st_blocks * 512;
res.is_dir_ = (buf.st_mode & S_IFMT) == S_IFDIR;
res.is_reg_ = (buf.st_mode & S_IFMT) == S_IFREG;
return res;

View File

@ -18,6 +18,7 @@ struct Stat {
bool is_dir_;
bool is_reg_;
int64 size_;
int64 real_size_;
uint64 atime_nsec_;
uint64 mtime_nsec_;
};

View File

@ -95,6 +95,22 @@ TEST(Port, files) {
ASSERT_STREQ("Habcd world?!", buf_slice.substr(0, 13));
}
TEST(Port, SparseFiles) {
CSlice path = "sparse.txt";
unlink(path).ignore();
auto fd = FileFd::open(path, FileFd::Write | FileFd::CreateNew).move_as_ok();
ASSERT_EQ(0, fd.get_size().move_as_ok());
ASSERT_EQ(0, fd.get_real_size().move_as_ok());
int64 offset = 100000000;
fd.pwrite("a", offset);
ASSERT_EQ(offset + 1, fd.get_size().move_as_ok());
auto real_size = fd.get_real_size().move_as_ok();
if (real_size == offset + 1) {
LOG(ERROR) << "File system doesn't support sparse files, rewind during streaming can be slow";
}
unlink(path).ensure();
}
TEST(Port, Writev) {
std::vector<IoSlice> vec;
CSlice test_file_path = "test.txt";