BadgerDB
 All Classes Namespaces Functions Variables Typedefs Friends
Public Member Functions | Static Public Member Functions | Friends
badgerdb::File Class Reference

Class which represents a file in the filesystem containing database pages. More...

#include <file.h>

List of all members.

Public Member Functions

 File (const File &other)
Fileoperator= (const File &rhs)
 ~File ()
Page allocatePage ()
Page readPage (const PageId page_number) const
void writePage (const Page &new_page)
void deletePage (const PageId page_number)
const std::string & filename () const
FileIterator begin ()
FileIterator end ()

Static Public Member Functions

static File create (const std::string &filename)
static File 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)

Friends

class FileIterator
class FileTest

Detailed Description

Class which represents a file in the filesystem containing database pages.

The File class wraps a stream to an underlying file on disk. Files contain fixed-sized pages, and they never deallocate space (though they do reuse deleted pages if possible). If multiple File objects refer to the same underlying file, they will share the stream in memory. If a file that has already been opened (possibly by another query), then the File class detects this (by looking in the open_streams_ map) and just returns a file object with the already created stream for the file without actually opening the UNIX file again.

Warning:
This class is not threadsafe.

Definition at line 73 of file file.h.


Constructor & Destructor Documentation

badgerdb::File::File ( const File other)

Copy constructor.

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

Definition at line 65 of file file.cpp.

  : filename_(other.filename_),
    stream_(open_streams_[filename_]) {
  ++open_counts_[filename_];
}

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

Definition at line 80 of file file.cpp.

            {
  close();
}

Member Function Documentation

Allocates a new page in the file.

Returns:
The new page.

Definition at line 84 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);
    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);
    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.page_number(), 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);
  }
  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 214 of file file.cpp.

                         {
  const FileHeader& header = readHeader();
  return FileIterator(this, header.first_used_page);
}
File badgerdb::File::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 29 of file file.cpp.

                                           {
  return File(filename, true /* create_new */);
}
void badgerdb::File::deletePage ( const PageId  page_number)

Deletes a page from the file.

Parameters:
page_numberNumber of page to delete.

Definition at line 184 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);
  }
  writePage(page_number, 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 219 of file file.cpp.

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

Returns true if the file exists and is open.

Parameters:
filenameName of the file.

Definition at line 54 of file file.cpp.

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

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

Returns the name of the file this object represents.

Returns:
Name of file.

Definition at line 179 of file file.h.

{ return filename_; }
bool badgerdb::File::isOpen ( const std::string &  filename) [static]

Returns true if the file exists and is open.

Parameters:
filenameName of the file.

Definition at line 47 of file file.cpp.

                                           {
  if (!exists(filename)) {
    return false;
  }
  return open_counts_.find(filename) != open_counts_.end();
}
File badgerdb::File::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 33 of file file.cpp.

                                         {
  return File(filename, false /* create_new */);
}
File & badgerdb::File::operator= ( const File rhs)

Assignment operator.

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

Definition at line 71 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;
}
Page badgerdb::File::readPage ( const PageId  page_number) const

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.

Definition at line 149 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]

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 37 of file file.cpp.

                                           {
  if (!exists(filename)) {
    throw FileNotFoundException(filename);
  }
  if (isOpen(filename)) {
    throw FileOpenException(filename);
  }
  std::remove(filename.c_str());
}
void badgerdb::File::writePage ( const Page new_page)

Writes a page into the file, replacing any existing contents. The page must have been already allocated in this file by a call to allocatePage().

See also:
allocatePage()
Parameters:
new_pagePage to write.

Definition at line 169 of file file.cpp.

                                         {
  PageHeader header = readPageHeader(new_page.page_number());
  if (header.current_page_number == Page::INVALID_NUMBER) {
    // Page has been deleted since it was read.
    throw InvalidPageException(new_page.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.page_number(), header, new_page);
}

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