BadgerDB
/afs/cs.wisc.edu/p/course/cs564-jignesh/public/html/projects/BadgerDB/bufmgr/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 
00215   PageIterator end();
00216 
00217  private:
00221   void initialize();
00222 
00228   void set_page_number(const PageId new_page_number) {
00229     header_.current_page_number = new_page_number;
00230   }
00231 
00237   void set_next_page_number(const PageId new_next_page_number) {
00238     header_.next_page_number = new_next_page_number;
00239   }
00240 
00251   void deleteRecord(const RecordId& record_id,
00252                     const bool allow_slot_compaction);
00253 
00262   PageSlot* getSlot(const SlotId slot_number);
00263 
00272   const PageSlot& getSlot(const SlotId slot_number) const;
00273 
00288   SlotId getAvailableSlot();
00289 
00303   void insertRecordInSlot(const SlotId slot_number,
00304                           const std::string& record_data);
00305 
00314   void validateRecordId(const RecordId& record_id) const;
00315 
00321   bool isUsed() const { return page_number() != INVALID_NUMBER; }
00322 
00326   PageHeader header_;
00327 
00333   std::string data_;
00334 
00335   friend class File;
00336   friend class PageIterator;
00337   friend class PageTest;
00338   friend class BufferTest;
00339 };
00340 
00341 static_assert(Page::SIZE > sizeof(PageHeader),
00342               "Page size must be large enough to hold header and data.");
00343 static_assert(Page::DATA_SIZE > 0,
00344               "Page must have some space to hold data.");
00345 
00346 }
 All Classes Namespaces Functions Variables Typedefs Friends