Finish step 5
This commit is contained in:
parent
103ab099c1
commit
f85583c4cc
75
db.c
75
db.c
@ -114,8 +114,70 @@ void read_input(InputBuffer* input_buffer) {
|
|||||||
input_buffer->buffer[bytes_read - 1] = 0;
|
input_buffer->buffer[bytes_read - 1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaCommandResult do_meta_command(InputBuffer* input_buffer) {
|
void pager_flush(Pager* pager, uint32_t page_num, uint32_t size) {
|
||||||
|
if (pager->pages[page_num] == NULL) {
|
||||||
|
printf("Tried to flush null page\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t offset = lseek(pager->file_descriptor, page_num * PAGE_SIZE, SEEK_SET);
|
||||||
|
|
||||||
|
if (offset == -1) {
|
||||||
|
printf("Error seeking: %d\n", errno);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t bytes_written = write(pager->file_descriptor, pager->pages[page_num], size);
|
||||||
|
|
||||||
|
if (bytes_written == -1) {
|
||||||
|
printf("Error writing: %d\n", errno);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void db_close(Table* table) {
|
||||||
|
Pager* pager = table->pager;
|
||||||
|
uint32_t num_full_pages = table->num_rows / ROWS_PER_PAGE;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < num_full_pages; i++) {
|
||||||
|
if (pager->pages[i] == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pager_flush(pager, i, PAGE_SIZE);
|
||||||
|
free(pager->pages[i]);
|
||||||
|
pager->pages[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// There may be a partial page to write to the end of the file
|
||||||
|
// This should not be needed after we switch to a B-tree
|
||||||
|
uint32_t num_additional_rows = table->num_rows % ROWS_PER_PAGE;
|
||||||
|
if (num_additional_rows > 0) {
|
||||||
|
uint32_t page_num = num_full_pages;
|
||||||
|
if (pager->pages[page_num] != NULL) {
|
||||||
|
pager_flush(pager, page_num, num_additional_rows * ROW_SIZE);
|
||||||
|
free(pager->pages[page_num]);
|
||||||
|
pager->pages[page_num] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = close(pager->file_descriptor);
|
||||||
|
if (result == -1) {
|
||||||
|
printf("Error closing db file.\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
for(uint32_t i = 0; i < TABLE_MAX_PAGES; i++) {
|
||||||
|
void* page = pager->pages[i];
|
||||||
|
if (page) {
|
||||||
|
free(page);
|
||||||
|
pager->pages[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(pager);
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaCommandResult do_meta_command(InputBuffer* input_buffer, Table* table) {
|
||||||
if (strcmp(input_buffer->buffer, ".exit") == 0) {
|
if (strcmp(input_buffer->buffer, ".exit") == 0) {
|
||||||
|
db_close(table);
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
} else {
|
} else {
|
||||||
return META_COMMAND_UNRECOGNIZED_COMMAND;
|
return META_COMMAND_UNRECOGNIZED_COMMAND;
|
||||||
@ -285,14 +347,21 @@ Table* db_open(const char* filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
Table* table = new_table();
|
if (argc < 2) {
|
||||||
|
printf("Must supply a database filename\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* filename = argv[1];
|
||||||
|
Table* table = db_open(filename);
|
||||||
|
|
||||||
InputBuffer* input_buffer = new_input_buffer();
|
InputBuffer* input_buffer = new_input_buffer();
|
||||||
while (true) {
|
while (true) {
|
||||||
print_prompt();
|
print_prompt();
|
||||||
read_input(input_buffer);
|
read_input(input_buffer);
|
||||||
|
|
||||||
if (input_buffer->buffer[0] == '.') {
|
if (input_buffer->buffer[0] == '.') {
|
||||||
switch (do_meta_command(input_buffer)) {
|
switch (do_meta_command(input_buffer, table)) {
|
||||||
case (META_COMMAND_SUCCESS):
|
case (META_COMMAND_SUCCESS):
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
describe 'database' do
|
describe 'database' do
|
||||||
|
before do
|
||||||
|
`rm -rf test.db`
|
||||||
|
end
|
||||||
|
|
||||||
def run_script(commands)
|
def run_script(commands)
|
||||||
raw_output = nil
|
raw_output = nil
|
||||||
IO.popen("./db", "r+") do |pipe|
|
IO.popen("./db test.db", "r+") do |pipe|
|
||||||
commands.each do |command|
|
commands.each do |command|
|
||||||
pipe.puts command
|
pipe.puts command
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user