BadgerDB
/afs/cs.wisc.edu/u/m/o/mohan/private/cs564/btree/btree/src/page.h
00001 
00008 #pragma once
00009 
00010 #include <cstddef>
00011 #include <stdint.h>
00012 #include <memory>
00013 #include <string>
00014 
00015 //#include <gtest/gtest.h>
00016 #include "types.h"
00017 
00018 namespace badgerdb {
00019 
00026 struct PageHeader {
00031   std::uint16_t free_space_lower_bound;
00032 
00037   std::uint16_t free_space_upper_bound;
00038 
00044   SlotId num_slots;
00045 
00049   SlotId num_free_slots;
00050 
00054   PageId current_page_number;
00055 
00059   PageId next_page_number;
00060 
00067   bool operator==(const PageHeader& rhs) const {
00068     return num_slots == rhs.num_slots &&
00069         num_free_slots == rhs.num_free_slots &&
00070         current_page_number == rhs.current_page_number &&
00071         next_page_number == rhs.next_page_number;
00072   }
00073 };
00074 
00078 struct PageSlot {
00083   bool used;
00084 
00088   std::uint16_t item_offset;
00089 
00093   std::uint16_t item_length;
00094 };
00095 
00096 class PageIterator;
00097 
00108 class Page {
00109  public:
00114   static const std::size_t SIZE = 8192;
00115 
00119   static const std::size_t DATA_SIZE = SIZE - sizeof(PageHeader);
00120 
00124   static const PageId INVALID_NUMBER = 0;
00125 
00129   static const SlotId INVALID_SLOT = 0;
00130 
00134   Page();
00135 
00142   RecordId insertRecord(const std::string& record_data);
00143 
00152   std::string getRecord(const RecordId& record_id) const;
00153 
00162   void updateRecord(const RecordId& record_id, const std::string& record_data);
00163 
00171   void deleteRecord(const RecordId& record_id);
00172 
00179   bool hasSpaceForRecord(const std::string& record_data) const;
00180 
00186   std::uint16_t getFreeSpace() const { return header_.free_space_upper_bound -
00187                                               header_.free_space_lower_bound; }
00188 
00194   PageId page_number() const { return header_.current_page_number; }
00195 
00201   PageId next_page_number() const { return header_.next_page_number; }
00202 
00208   PageIterator begin();
00209 
00216   PageIterator end();
00217 
00218  private:
00222   void initialize();
00223 
00229   void set_page_number(const PageId new_page_number) {
00230     header_.current_page_number = new_page_number;
00231   }
00232 
00238   void set_next_page_number(const PageId new_next_page_number) {
00239     header_.next_page_number = new_next_page_number;
00240   }
00241 
00252   void deleteRecord(const RecordId& record_id,
00253                     const bool allow_slot_compaction);
00254 
00263   PageSlot* getSlot(const SlotId slot_number);
00264 
00273   const PageSlot& getSlot(const SlotId slot_number) const;
00274 
00289   SlotId getAvailableSlot();
00290 
00304   void insertRecordInSlot(const SlotId slot_number,
00305                           const std::string& record_data);
00306 
00315   void validateRecordId(const RecordId& record_id) const;
00316 
00322   bool isUsed() const { return page_number() != INVALID_NUMBER; }
00323 
00327   PageHeader header_;
00328 
00334   char data_[DATA_SIZE];
00335 
00336   friend class File;
00337   friend class PageFile;
00338   friend class BlobFile;
00339   friend class PageIterator;
00340 };
00341 
00342 static_assert(Page::SIZE > sizeof(PageHeader),
00343               "Page size must be large enough to hold header and data.");
00344 static_assert(Page::DATA_SIZE > 0,
00345               "Page must have some space to hold data.");
00346 
00347 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Friends