Skip to content

Commit e3f44c3

Browse files
committed
Better R/W but only if multithreaded :(
1 parent 5f1aad8 commit e3f44c3

File tree

2 files changed

+44
-68
lines changed

2 files changed

+44
-68
lines changed

src/include/storage/disk/disk_manager.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ class DiskManager {
100100
// stream to write db file
101101
std::fstream db_io_;
102102
std::string file_name_;
103+
int db_fd_;
104+
int log_fd_;
105+
103106
int num_flushes_{0};
104107
int num_writes_{0};
105108
bool flush_log_{false};

src/storage/disk/disk_manager.cpp

Lines changed: 41 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "common/exception.h"
2222
#include "common/logger.h"
2323
#include "storage/disk/disk_manager.h"
24+
#include <unistd.h>
25+
#include <fcntl.h>
2426

2527
namespace bustub {
2628

@@ -38,40 +40,32 @@ DiskManager::DiskManager(const std::string &db_file) : file_name_(db_file) {
3840
}
3941
log_name_ = file_name_.substr(0, n) + ".log";
4042

41-
log_io_.open(log_name_, std::ios::binary | std::ios::in | std::ios::app | std::ios::out);
42-
// directory or file does not exist
43-
if (!log_io_.is_open()) {
44-
log_io_.clear();
45-
// create a new file
46-
log_io_.open(log_name_, std::ios::binary | std::ios::trunc | std::ios::out | std::ios::in);
47-
if (!log_io_.is_open()) {
48-
throw Exception("can't open dblog file");
49-
}
43+
// Open log file using file descriptor
44+
log_fd_ = open(log_name_.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
45+
if (log_fd_ < 0) {
46+
throw Exception("can't open log file");
5047
}
5148

52-
std::scoped_lock scoped_db_io_latch(db_io_latch_);
53-
db_io_.open(db_file, std::ios::binary | std::ios::in | std::ios::out);
54-
// directory or file does not exist
55-
if (!db_io_.is_open()) {
56-
db_io_.clear();
57-
// create a new file
58-
db_io_.open(db_file, std::ios::binary | std::ios::trunc | std::ios::out | std::ios::in);
59-
if (!db_io_.is_open()) {
60-
throw Exception("can't open db file");
61-
}
49+
// Open db file using file descriptor
50+
db_fd_ = open(db_file.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
51+
if (db_fd_ < 0) {
52+
close(log_fd_);
53+
throw Exception("can't open db file");
6254
}
55+
6356
buffer_used = nullptr;
6457
}
6558

59+
6660
/**
6761
* Close all file streams
6862
*/
6963
void DiskManager::ShutDown() {
7064
{
7165
std::scoped_lock scoped_db_io_latch(db_io_latch_);
72-
db_io_.close();
66+
close(db_fd_); // Close the db file descriptor
7367
}
74-
log_io_.close();
68+
close(log_fd_); // Close the log file descriptor
7569
}
7670

7771
/**
@@ -80,19 +74,16 @@ void DiskManager::ShutDown() {
8074
void DiskManager::WritePage(page_id_t page_id, const char *page_data) {
8175
std::scoped_lock scoped_db_io_latch(db_io_latch_);
8276
size_t offset = static_cast<size_t>(page_id) * BUSTUB_PAGE_SIZE;
83-
// set write cursor to offset
84-
num_writes_ += 1;
85-
db_io_.seekp(offset);
86-
db_io_.write(page_data, BUSTUB_PAGE_SIZE);
87-
// check for I/O error
88-
if (db_io_.bad()) {
89-
LOG_DEBUG("I/O error while writing");
77+
78+
ssize_t bytes_written = pwrite(db_fd_, page_data, BUSTUB_PAGE_SIZE, offset);
79+
if (bytes_written == -1) {
80+
LOG_DEBUG("I/O error while writing with pwrite");
9081
return;
9182
}
92-
// needs to flush to keep disk file in sync
93-
db_io_.flush();
83+
num_writes_ += 1;
9484
}
9585

86+
9687
/**
9788
* Read the contents of the specified page into the given memory area
9889
*/
@@ -102,22 +93,18 @@ void DiskManager::ReadPage(page_id_t page_id, char *page_data) {
10293
// check if read beyond file length
10394
if (offset > GetFileSize(file_name_)) {
10495
LOG_DEBUG("I/O error reading past end of file");
105-
// std::cerr << "I/O error while reading" << std::endl;
10696
} else {
107-
// set read cursor to offset
108-
db_io_.seekp(offset);
109-
db_io_.read(page_data, BUSTUB_PAGE_SIZE);
110-
if (db_io_.bad()) {
111-
LOG_DEBUG("I/O error while reading");
97+
98+
ssize_t bytes_read = pread(db_fd_, page_data, BUSTUB_PAGE_SIZE, offset);
99+
if (bytes_read == -1) {
100+
LOG_DEBUG("I/O error while reading with pread");
112101
return;
113102
}
114-
// if file ends before reading BUSTUB_PAGE_SIZE
115-
int read_count = db_io_.gcount();
116-
if (read_count < BUSTUB_PAGE_SIZE) {
103+
104+
// If file ends before reading BUSTUB_PAGE_SIZE
105+
if (bytes_read < BUSTUB_PAGE_SIZE) {
117106
LOG_DEBUG("Read less than a page");
118-
db_io_.clear();
119-
// std::cerr << "Read less than a page" << std::endl;
120-
memset(page_data + read_count, 0, BUSTUB_PAGE_SIZE - read_count);
107+
memset(page_data + bytes_read, 0, BUSTUB_PAGE_SIZE - bytes_read);
121108
}
122109
}
123110
}
@@ -127,7 +114,6 @@ void DiskManager::ReadPage(page_id_t page_id, char *page_data) {
127114
* Only return when sync is done, and only perform sequence write
128115
*/
129116
void DiskManager::WriteLog(char *log_data, int size) {
130-
// enforce swap log buffer
131117
assert(log_data != buffer_used);
132118
buffer_used = log_data;
133119

@@ -137,48 +123,35 @@ void DiskManager::WriteLog(char *log_data, int size) {
137123

138124
flush_log_ = true;
139125

140-
if (flush_log_f_ != nullptr) {
141-
// used for checking non-blocking flushing
142-
assert(flush_log_f_->wait_for(std::chrono::seconds(10)) == std::future_status::ready);
143-
}
144-
145126
num_flushes_ += 1;
146-
// sequence write
147-
log_io_.write(log_data, size);
148-
149-
// check for I/O error
150-
if (log_io_.bad()) {
151-
LOG_DEBUG("I/O error while writing log");
127+
ssize_t bytes_written = pwrite(log_fd_, log_data, size, 0); // Always appending
128+
if (bytes_written == -1) {
129+
LOG_DEBUG("I/O error while writing log with pwrite");
152130
return;
153131
}
154-
// needs to flush to keep disk file in sync
155-
log_io_.flush();
132+
156133
flush_log_ = false;
157134
}
158135

136+
159137
/**
160138
* Read the contents of the log into the given memory area
161139
* Always read from the beginning and perform sequence read
162140
* @return: false means already reach the end
163141
*/
164-
auto DiskManager::ReadLog(char *log_data, int size, int offset) -> bool {
142+
bool DiskManager::ReadLog(char *log_data, int size, int offset) {
165143
if (offset >= GetFileSize(log_name_)) {
166-
// LOG_DEBUG("end of log file");
167-
// LOG_DEBUG("file size is %d", GetFileSize(log_name_));
168144
return false;
169145
}
170-
log_io_.seekp(offset);
171-
log_io_.read(log_data, size);
172146

173-
if (log_io_.bad()) {
174-
LOG_DEBUG("I/O error while reading log");
147+
ssize_t bytes_read = pread(log_fd_, log_data, size, offset);
148+
if (bytes_read == -1) {
149+
LOG_DEBUG("I/O error while reading log with pread");
175150
return false;
176151
}
177-
// if log file ends before reading "size"
178-
int read_count = log_io_.gcount();
179-
if (read_count < size) {
180-
log_io_.clear();
181-
memset(log_data + read_count, 0, size - read_count);
152+
153+
if (bytes_read < size) {
154+
memset(log_data + bytes_read, 0, size - bytes_read);
182155
}
183156

184157
return true;

0 commit comments

Comments
 (0)