BadgerDB
/afs/cs.wisc.edu/u/n/w/nwilliam/private/workspace/Quut/src/page.h
00001 
00008 #pragma once
00009 
00010 #include <cstddef>
00011 #include <stdint.h>
00012 #include <memory>
00013 #include <string>
00014 
00015 #include "types.h"
00016 
00017 namespace badgerdb {
00018 
00025 struct PageHeader {
00030   std::uint16_t free_space_lower_bound;
00031 
00036   std::uint16_t free_space_upper_bound;
00037 
00043   SlotId num_slots;
00044 
00048   SlotId num_free_slots;
00049 
00053   PageId current_page_number;
00054 
00058   PageId next_page_number;
00059 
00066   bool operator==(const PageHeader& rhs) const {
00067     return num_slots == rhs.num_slots &&
00068         num_free_slots == rhs.num_free_slots &&
00069         current_page_number == rhs.current_page_number &&
00070         next_page_number == rhs.next_page_number;
00071   }
00072 };
00073 
00077 struct PageSlot {
00082   bool used;
00083 
00087   std::uint16_t item_offset;
00088 
00092   std::uint16_t item_length;
00093 };
00094 
00095 class PageIterator;
00096 
00107 class Page {
00108  public:
00113   static const std::size_t SIZE = 8192;
00114 
00118   static const std::size_t DATA_SIZE = SIZE - sizeof(PageHeader);
00119 
00123   static const PageId INVALID_NUMBER = 0;
00124 
00128   static const SlotId INVALID_SLOT = 0;
00129 
00133   Page();
00134 
00141   RecordId insertRecord(const std::string& record_data);
00142 
00151   std::string getRecord(const RecordId& record_id) const;
00152 
00161   void updateRecord(const RecordId& record_id, const std::string& record_data);
00162 
00170   void deleteRecord(const RecordId& record_id);
00171 
00178   bool hasSpaceForRecord(const std::string& record_data) const;
00179 
00185   std::uint16_t getFreeSpace() const { return header_.free_space_upper_bound -
00186                                               header_.free_space_lower_bound; }
00187 
00193   PageId page_number() const { return header_.current_page_number; }
00194 
00200   PageId next_page_number() const { return header_.next_page_number; }
00201 
00207   PageIterator begin();
00208 
00214   PageIterator beginAt(SlotId slot);
00215 
00222   PageIterator end();
00223 
00224  private:
00228   void initialize();
00229 
00235   void set_page_number(const PageId new_page_number) {
00236     header_.current_page_number = new_page_number;
00237   }
00238 
00244   void set_next_page_number(const PageId new_next_page_number) {
00245     header_.next_page_number = new_next_page_number;
00246   }
00247 
00258   void deleteRecord(const RecordId& record_id,
00259                     const bool allow_slot_compaction);
00260 
00269   PageSlot* getSlot(const SlotId slot_number);
00270 
00279   const PageSlot& getSlot(const SlotId slot_number) const;
00280 
00295   SlotId getAvailableSlot();
00296 
00310   void insertRecordInSlot(const SlotId slot_number,
00311                           const std::string& record_data);
00312 
00321   void validateRecordId(const RecordId& record_id) const;
00322 
00328   bool isUsed() const { return page_number() != INVALID_NUMBER; }
00329 
00333   PageHeader header_;
00334 
00340   char data_[DATA_SIZE];
00341 
00342   friend class File;
00343   friend class PageFile;
00344   friend class BlobFile;
00345   friend class PageIterator;
00346 };
00347 
00348 static_assert(Page::SIZE > sizeof(PageHeader),
00349               "Page size must be large enough to hold header and data.");
00350 static_assert(Page::DATA_SIZE > 0,
00351               "Page must have some space to hold data.");
00352 
00353 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Friends