17 #include "exceptions/file_exists_exception.h"
18 #include "exceptions/file_not_found_exception.h"
19 #include "exceptions/file_open_exception.h"
20 #include "exceptions/invalid_page_exception.h"
21 #include "file_iterator.h"
26 File::StreamMap File::open_streams_;
27 File::CountMap File::open_counts_;
30 return File(filename,
true );
34 return File(filename,
false );
44 std::remove(filename.c_str());
51 return open_counts_.find(filename) != open_counts_.end();
55 std::fstream file(filename);
66 : filename_(other.filename_),
67 stream_(open_streams_[filename_]) {
68 ++open_counts_[filename_];
75 filename_ = rhs.filename_;
107 next_page_number = (*iter).next_page_number();
110 existing_page = *iter;
114 existing_page.set_next_page_number(new_page.
page_number());
115 new_page.set_next_page_number(next_page_number);
121 new_page.set_page_number(header.
num_pages);
129 existing_page = *iter;
133 assert(existing_page.isUsed());
134 existing_page.set_next_page_number(new_page.
page_number());
154 return readPage(page_number,
false );
159 stream_->seekg(pagePosition(page_number), std::ios::beg);
160 stream_->read(reinterpret_cast<char*>(&page.header_),
sizeof(page.header_));
161 stream_->read(reinterpret_cast<char*>(&page.data_[0]),
Page::DATA_SIZE);
162 if (!allow_free && !page.isUsed()) {
179 header = new_page.header_;
195 previous_page = *iter;
203 existing_page.initialize();
207 if (previous_page.isUsed()) {
223 File::File(
const std::string& name,
const bool create_new) : filename_(name) {
224 openIfNeeded(create_new);
234 void File::openIfNeeded(
const bool create_new) {
235 if (open_counts_.find(filename_) != open_counts_.end()) {
236 ++open_counts_[filename_];
237 stream_ = open_streams_[filename_];
239 std::ios_base::openmode mode =
240 std::fstream::in | std::fstream::out | std::fstream::binary;
241 const bool already_exists =
exists(filename_);
244 if (already_exists) {
245 throw FileExistsException(filename_);
248 mode = mode | std::fstream::trunc;
251 if (!already_exists) {
252 throw FileNotFoundException(filename_);
255 stream_.reset(
new std::fstream(filename_, mode));
256 open_streams_[filename_] = stream_;
257 open_counts_[filename_] = 1;
262 --open_counts_[filename_];
264 if (open_counts_[filename_] == 0) {
265 open_streams_.erase(filename_);
266 open_counts_.erase(filename_);
271 writePage(page_number, new_page.header_, new_page);
275 const Page& new_page) {
276 stream_->seekp(pagePosition(page_number), std::ios::beg);
277 stream_->write(reinterpret_cast<const char*>(&header),
sizeof(header));
278 stream_->write(reinterpret_cast<const char*>(&new_page.data_[0]),
283 FileHeader File::readHeader()
const {
285 stream_->seekg(0 , std::ios::beg);
286 stream_->read(reinterpret_cast<char*>(&header),
sizeof(header));
291 void File::writeHeader(
const FileHeader& header) {
292 stream_->seekp(0 , std::ios::beg);
293 stream_->write(reinterpret_cast<const char*>(&header),
sizeof(header));
297 PageHeader File::readPageHeader(
PageId page_number)
const {
299 stream_->seekg(pagePosition(page_number), std::ios::beg);
300 stream_->read(reinterpret_cast<char*>(&header),
sizeof(header));
static bool isOpen(const std::string &filename)
PageId next_page_number() const
static File open(const std::string &filename)
Class which represents a file in the filesystem containing database pages.
static const std::size_t DATA_SIZE
static File create(const std::string &filename)
std::uint32_t PageId
Identifier for a page in a file.
An exception that is thrown when a file operation is requested for a filename that doesn't exist...
An exception that is thrown when an attempt is made to access an invalid page in a file...
Class which represents a fixed-size database page containing records.
void writePage(const Page &new_page)
An exception that is thrown when a file deletion is requested for a filename that's currently open...
PageId page_number() const
Iterator for iterating over the pages in a file.
static void remove(const std::string &filename)
Page readPage(const PageId page_number) const
File & operator=(const File &rhs)
static const PageId INVALID_NUMBER
static bool exists(const std::string &filename)
void deletePage(const PageId page_number)