BadgerDB
 All Classes Namespaces Functions Variables Typedefs Enumerations Friends
Public Member Functions | Static Public Member Functions | Protected Types | Protected Member Functions | Static Protected Member Functions | Protected Attributes | Static Protected Attributes | Friends
badgerdb::PageFile Class Reference
Inheritance diagram for badgerdb::PageFile:
badgerdb::File

List of all members.

Public Member Functions

 PageFile (const std::string &name, const bool create_new)
 PageFile (const PageFile &other)
PageFileoperator= (const PageFile &rhs)
 ~PageFile ()
Page allocatePage (PageId &new_page_number)
Page readPage (const PageId page_number) const
void writePage (const PageId page_number, const Page &new_page)
void deletePage (const PageId page_number)
FileIterator begin ()
FileIterator end ()
const std::string & filename () const
PageId getFirstPageNo ()

Static Public Member Functions

static PageFile create (const std::string &filename)
static PageFile open (const std::string &filename)
static void remove (const std::string &filename)
static bool isOpen (const std::string &filename)
static bool exists (const std::string &filename)

Protected Types

typedef std::map< std::string,
std::shared_ptr< std::fstream > > 
StreamMap
typedef std::map< std::string,
int > 
CountMap

Protected Member Functions

void openIfNeeded (const bool create_new)
void close ()
FileHeader readHeader () const
void writeHeader (const FileHeader &header)

Static Protected Member Functions

static std::streampos pagePosition (const PageId page_number)

Protected Attributes

std::string filename_
std::shared_ptr< std::fstream > stream_

Static Protected Attributes

static StreamMap open_streams_
static CountMap open_counts_

Friends

class FileIterator

Detailed Description

Definition at line 239 of file file.h.


Constructor & Destructor Documentation

badgerdb::PageFile::PageFile ( const std::string &  name,
const bool  create_new 
)

Constructs a file object representing a file on the filesystem.

Parameters:
nameName of file.
create_newWhether to create a new file.
Exceptions:
FileExistsExceptionIf the underlying file exists and create_new is true.
FileNotFoundExceptionIf the underlying file doesn't exist and create_new is false.

Definition at line 143 of file file.cpp.

: File(name, create_new)
{
}

Copy constructor.

Parameters:
otherFile object to copy.
Returns:
A copy of the File object.

Definition at line 151 of file file.cpp.

: File(other.filename_, false /* create_new */)
{
}

Destructor that automatically closes the underlying file if no other File objects are using it.

Definition at line 148 of file file.cpp.

                    {
}

Member Function Documentation

Page badgerdb::PageFile::allocatePage ( PageId new_page_number) [virtual]

Allocates a new page in the file.

Returns:
The new page.

Implements badgerdb::File.

Definition at line 165 of file file.cpp.

                                                   {
  FileHeader header = readHeader();
  Page new_page;
  Page existing_page;
  if (header.num_free_pages > 0) {
    new_page = readPage(header.first_free_page, true /* allow_free */);
    new_page.set_page_number(header.first_free_page);
    new_page_number = new_page.page_number();
    header.first_free_page = new_page.next_page_number();
    --header.num_free_pages;

    if (header.first_used_page == Page::INVALID_NUMBER ||
        header.first_used_page > new_page.page_number()) {
      // Either have no pages used or the head of the used list is a page later
      // than the one we just allocated, so add the new page to the head.
      if (header.first_used_page > new_page.page_number()) {
        new_page.set_next_page_number(header.first_used_page);
      }
      header.first_used_page = new_page.page_number();
    } else {
      // New page is reused from somewhere after the beginning, so we need to
      // find where in the used list to insert it.
      PageId next_page_number = Page::INVALID_NUMBER;
      for (FileIterator iter = begin(); iter != end(); ++iter) {
        next_page_number = (*iter).next_page_number();
        if (next_page_number > new_page.page_number() ||
            next_page_number == Page::INVALID_NUMBER) {
          existing_page = *iter;
          break;
        }
      }
      existing_page.set_next_page_number(new_page.page_number());
      new_page.set_next_page_number(next_page_number);
    }

    assert((header.num_free_pages == 0) ==
           (header.first_free_page == Page::INVALID_NUMBER));
  }
  else
  {
    new_page.set_page_number(header.num_pages);
    new_page_number = new_page.page_number();

    if (header.first_used_page == Page::INVALID_NUMBER)
    {
      header.first_used_page = new_page.page_number();
    }
    else
    {
      // If we have pages allocated, we need to add the new page to the tail
      // of the linked list.
      for (FileIterator iter = begin(); iter != end(); ++iter) {
        if ((*iter).next_page_number() == Page::INVALID_NUMBER) {
          existing_page = *iter;
          break;
        }
      }
      assert(existing_page.isUsed());
      existing_page.set_next_page_number(new_page.page_number());
    }
    ++header.num_pages;
  }
  writePage(new_page_number, new_page.header_, new_page);
  if (existing_page.page_number() != Page::INVALID_NUMBER) {
    // If we updated an existing page by inserting the new page into the
    // used list, we need to write it out.
    writePage(existing_page.page_number(), existing_page.header_, existing_page);
  }
  writeHeader(header);

  return new_page;
}

Returns an iterator at the first page in the file.

Returns:
Iterator at first page of file.

Definition at line 307 of file file.cpp.

                             {
  const FileHeader& header = readHeader();
  return FileIterator(this, header.first_used_page);
}
void badgerdb::File::close ( ) [protected, inherited]

Closes the underlying file stream in <stream_>. This method only closes the file if no other File objects exist that access the same file.

Definition at line 105 of file file.cpp.

PageFile badgerdb::PageFile::create ( const std::string &  filename) [static]

Creates a new file.

Parameters:
filenameName of the file.
Exceptions:
FileExistsExceptionIf the requested file already exists.

Definition at line 135 of file file.cpp.

                                                   {
  return PageFile(filename, true /* create_new */);
}
void badgerdb::PageFile::deletePage ( const PageId  page_number) [virtual]

Deletes a page from the file.

Parameters:
page_numberNumber of page to delete.

Implements badgerdb::File.

Definition at line 276 of file file.cpp.

                                                  {
  FileHeader header = readHeader();

  Page existing_page = readPage(page_number);
  Page previous_page;
  // If this page is the head of the used list, update the header to point to
  // the next page in line.
  if (page_number == header.first_used_page) {
    header.first_used_page = existing_page.next_page_number();
  } else {
    // Walk the used list so we can update the page that points to this one.
    for (FileIterator iter = begin(); iter != end(); ++iter) {
      previous_page = *iter;
      if (previous_page.next_page_number() == existing_page.page_number()) {
        previous_page.set_next_page_number(existing_page.next_page_number());
        break;
      }
    }
  }
  // Clear the page and add it to the head of the free list.
  existing_page.initialize();
  existing_page.set_next_page_number(header.first_free_page);
  header.first_free_page = page_number;
  ++header.num_free_pages;
  if (previous_page.isUsed()) {
    writePage(previous_page.page_number(), previous_page.header_, previous_page);
  }
  writePage(page_number, existing_page.header_, existing_page);
  writeHeader(header);
}

Returns an iterator representing the page after the last page in the file. This iterator should not be dereferenced.

Returns:
Iterator representing page after the last page in the file.

Definition at line 312 of file file.cpp.

                           {
  return FileIterator(this, Page::INVALID_NUMBER);
}
bool badgerdb::File::exists ( const std::string &  filename) [static, inherited]

Returns true if the file exists and is open.

Parameters:
filenameName of the file.

Definition at line 46 of file file.cpp.

                                           {
  std::fstream file(filename);
  if(file)
  {
    file.close();
    return true;
  }

  return false;
}
const std::string& badgerdb::File::filename ( ) const [inline, inherited]

Returns the name of the file this object represents.

Returns:
Name of file.

Definition at line 158 of file file.h.

{ return filename_; }

Returns pageid of first page in the file.

Returns:
Iterator at first page of file.

Definition at line 62 of file file.cpp.

                            {
  const FileHeader& header = readHeader();
  return header.first_used_page;
}
bool badgerdb::File::isOpen ( const std::string &  filename) [static, inherited]

Returns true if the file exists and is open.

Parameters:
filenameName of the file.

Definition at line 39 of file file.cpp.

                                           {
  if (!exists(filename)) {
    return false;
  }
  return open_counts_.find(filename) != open_counts_.end();
}
PageFile badgerdb::PageFile::open ( const std::string &  filename) [static]

Opens the file named fileName and returns the corresponding File object. It first checks if the file is already open. If so, then the new File object created uses the same input-output stream to read to or write fom that already open file. Reference count (open_counts_ static variable inside the File object) is incremented whenever an already open file is opened again. Otherwise the UNIX file is actually opened. The fileName and the stream associated with this File object are inserted into the open_streams_ map.

Parameters:
filenameName of the file.
Exceptions:
FileNotFoundExceptionIf the requested file doesn't exist.

Definition at line 139 of file file.cpp.

                                                 {
  return PageFile(filename, false /* create_new */);
}
void badgerdb::File::openIfNeeded ( const bool  create_new) [protected, inherited]

Opens the underlying file named in filename_. This method only opens the file if no other File objects exist that access the same filesystem file; otherwise, it reuses the existing stream.

Parameters:
create_newWhether to create a new file.
Exceptions:
FileExistsExceptionIf the underlying file exists and create_new is true.
FileNotFoundExceptionIf the underlying file doesn't exist and create_new is false.

Definition at line 78 of file file.cpp.

                                             {
  if (open_counts_.find(filename_) != open_counts_.end()) { //exists an entry already
    ++open_counts_[filename_];
    stream_ = open_streams_[filename_];
  } else {
    std::ios_base::openmode mode =
        std::fstream::in | std::fstream::out | std::fstream::binary;
    const bool already_exists = exists(filename_);
    if (create_new) {
      // Error if we try to overwrite an existing file.
      if (already_exists) {
        throw FileExistsException(filename_);
      }
      // New files have to be truncated on open.
      mode = mode | std::fstream::trunc;
    } else {
      // Error if we try to open a file that doesn't exist.
      if (!already_exists) {
        throw FileNotFoundException(filename_);
      }
    }
    stream_.reset(new std::fstream(filename_, mode));
    open_streams_[filename_] = stream_;
    open_counts_[filename_] = 1;
  }
}
PageFile & badgerdb::PageFile::operator= ( const PageFile rhs)

Assignment operator.

Parameters:
rhsFile object to assign.
Returns:
Newly assigned file object.

Definition at line 156 of file file.cpp.

                                                 {
  // This accounts for self-assignment and assignment of a File object for the
  // same file.
  close();  //close my file and associate me with the new one
  filename_ = rhs.filename_;
  openIfNeeded(false /* create_new */);
  return *this;
}
static std::streampos badgerdb::File::pagePosition ( const PageId  page_number) [inline, static, protected, inherited]

Returns the position of the page with the given number in the file (as an offset from the beginning of the file).

Parameters:
page_numberNumber of page.
Returns:
Position of page in file.

Definition at line 175 of file file.h.

                                                             {
    return sizeof(FileHeader) + ((page_number - 1) * Page::SIZE);
  }
FileHeader badgerdb::File::readHeader ( ) const [protected, inherited]

Reads the header for this file from disk.

Returns:
The file header.

Definition at line 118 of file file.cpp.

                                  {
  FileHeader header;
  stream_->seekg(0 /* pos */, std::ios::beg);
  stream_->read(reinterpret_cast<char*>(&header), sizeof(FileHeader));
  return header;
}
Page badgerdb::PageFile::readPage ( const PageId  page_number) const [virtual]

Reads an existing page from the file.

Parameters:
page_numberNumber of page to read.
Returns:
The page.
Exceptions:
InvalidPageExceptionIf the page doesn't exist in the file or is not currently used.

Implements badgerdb::File.

Definition at line 238 of file file.cpp.

                                                      {
  FileHeader header = readHeader();

  if (page_number >= header.num_pages)
  {
    throw InvalidPageException(page_number, filename_);
  }
  return readPage(page_number, false /* allow_free */);
}
void badgerdb::File::remove ( const std::string &  filename) [static, inherited]

Deletes an existing file.

Parameters:
filenameName of the file.
Exceptions:
FileNotFoundExceptionIf the file doesn't exist.
FileOpenExceptionIf the file is currently open.

Definition at line 29 of file file.cpp.

                                           {
  if (!exists(filename)) {
    throw FileNotFoundException(filename);
  }
  if (isOpen(filename)) {
    throw FileOpenException(filename);
  }
  std::remove(filename.c_str());
}
void badgerdb::File::writeHeader ( const FileHeader header) [protected, inherited]

Writes the given header to the disk as the header for this file.

Parameters:
headerFile header to write.

Definition at line 125 of file file.cpp.

                                               {
  stream_->seekp(0 /* pos */, std::ios::beg);
  stream_->write(reinterpret_cast<const char*>(&header), sizeof(FileHeader));
  stream_->flush();
}
void badgerdb::PageFile::writePage ( const PageId  page_number,
const Page new_page 
) [virtual]

Writes a page into the file at the given page number. No bounds checking is performed.

Parameters:
page_numberNumber of page whose contents to replace.
new_pagePage to write.

Implements badgerdb::File.

Definition at line 260 of file file.cpp.

                                                                           {
  PageHeader header = readPageHeader(new_page_number);
  if (header.current_page_number == Page::INVALID_NUMBER)
  {
    // Page has been deleted since it was read.
    throw InvalidPageException(new_page_number, filename_);
  }
  // Page on disk may have had its next page pointer updated since it was read;
  // we don't modify that, but we do keep all the other modifications to the
  // page header.
  const PageId next_page_number = header.next_page_number;
  header = new_page.header_;
  header.next_page_number = next_page_number;
  writePage(new_page_number, header, new_page);
}

Member Data Documentation

std::string badgerdb::File::filename_ [protected, inherited]

Name of the file this object represents.

Definition at line 229 of file file.h.

File::CountMap badgerdb::File::open_counts_ [static, protected, inherited]

Counts for opened files.

Definition at line 224 of file file.h.

File::StreamMap badgerdb::File::open_streams_ [static, protected, inherited]

Streams for opened files.

Definition at line 219 of file file.h.

std::shared_ptr<std::fstream> badgerdb::File::stream_ [protected, inherited]

Stream for underlying filesystem object.

Definition at line 234 of file file.h.


The documentation for this class was generated from the following files:
 All Classes Namespaces Functions Variables Typedefs Enumerations Friends