#ifndef _SIMPLE_DATA_PAGE_H_ #define _SIMPLE_DATA_PAGE_H_ #include #include #include template class DataPage { public: class RecordIterator { public: RecordIterator(DataPage *dp) : read_offset_(0), dp(dp) { } RecordIterator(const RecordIterator &rhs) : read_offset_(rhs.read_offset_), dp(rhs.dp) {} void operator=(const RecordIterator &rhs) { this->read_offset_ = rhs.read_offset_; this->dp = rhs.dp; } //returns the next tuple and also advances the iterator TUPLE *getnext(int xid); //advance the iterator by count tuples, i.e. skip over count tuples void advance(int xid, int count=1); off_t read_offset_; DataPage *dp; }; public: //to be used when reading an existing data page from disk DataPage( int xid, pageid_t pid ); //to be used to create new data pages DataPage( int xid, int fix_pcount, pageid_t (*alloc_region)(int, void*), void * alloc_state); ~DataPage(); bool append(int xid, TUPLE const * dat); bool recordRead(int xid, typename TUPLE::key_t key, size_t keySize, TUPLE ** buf); inline uint16_t recordCount(int xid); RecordIterator begin(){return RecordIterator(this);} pageid_t get_start_pid(){return first_page_;} int get_page_count(){return page_count_;} static pageid_t dp_alloc_region(int xid, void *conf); static pageid_t dp_alloc_region_rid(int xid, void * ridp); static void dealloc_region_rid(int xid, void* conf); static void force_region_rid(int xid, void *conf); static void register_stasis_page_impl(); private: void initialize(int xid); //reads the page count information from the first page static int32_t readPageCount(int xid, pageid_t pid); private: static const uint16_t DATA_PAGE_HEADER_SIZE = sizeof(int32_t); static const uint16_t DATA_PAGE_SIZE = USABLE_SIZE_OF_PAGE - DATA_PAGE_HEADER_SIZE; typedef uint32_t len_t; static inline int32_t* page_count_ptr(Page *p) { return stasis_page_int32_ptr_from_start(p,0); } static inline byte * data_at_offset_ptr(Page *p, slotid_t offset) { return ((byte*)(page_count_ptr(p)+1))+offset; } static inline len_t * length_at_offset_ptr(Page *p, slotid_t offset) { return (len_t*)data_at_offset_ptr(p,offset); } inline recordid calc_chunk_from_offset(off_t offset) { recordid ret; ret.page = first_page_ + offset / DATA_PAGE_SIZE; ret.slot = offset % DATA_PAGE_SIZE; ret.size = DATA_PAGE_SIZE - ret.slot; assert(ret.size); return ret; } size_t write_bytes(int xid, const byte * buf, size_t remaining); size_t read_bytes(int xid, byte * buf, off_t offset, size_t remaining); bool write_data(int xid, const byte * buf, size_t len); bool read_data(int xid, byte * buf, off_t offset, size_t len); bool initialize_next_page(int xid); const int32_t page_count_; const pageid_t first_page_; off_t write_offset_; // points to the next free byte (ignoring page boundaries) }; #endif