#ifndef _ROSE_COMPRESSION_STATIC_MULTICOLUMN_H__ #define _ROSE_COMPRESSION_STATIC_MULTICOLUMN_H__ #include #include #include #include #include "compression.h" //#include "pstar.h" // for typedefs + consts (XXX add new header?) #include "tuple.h" // XXX rename tuple.hx //#include "pluginDispatcher.h" // Copyright 2007 Google Inc. All Rights Reserved. // Author: sears@google.com (Rusty Sears) /** @file Page implementation for multi-column, compressed data STRUCTURE OF A MULTICOLUMN PAGE
 +----------------------------------------------------------------------+
 | col #0 compressed data (opaque) | col #1 compressed data (opaque)    |
 +-----+---------------------------+-----+------------------------------|
 | ... | col  N compressed data (opaque) |                              |
 +-----+---------------------------------+                              |
 |  Free space                                                          |
 |                                                                      |
 |                                                                      |
 |                             +----------------------------------------+
 |                             | Exceptions:                            |
 +-----------------------------+ Includes data from multiple cols       |
 |                                                                      |
 | Exception data is managed (bytes are copied in and out of this       |
 | region) by the column implementations.  Multicolumn mediates between |
 | the columns, by recording the length and offset of this region.      |
 |                                                                      |
 |                                      +---------------+---------------+
 |                                  ... | exception # 1 | exception # 0 |
 +-----------------------+--------------------+----+--------------------+
 |  first header byte -> | col  N off, plugin | .. | col #1 off, plugin |
 +--------------------+--+-------------+------+----+----+-----------+---+
 | col #0 off, plugin | exceptions len | exceptions off | # of cols | ? |
 +--------------------+----------------+----------------+-----------+---+
Notes: The 'exceptions' portion of the page grows down from first_header_byte, while the column data portion grows up from byte zero... This was an arbitrary decision, and complicated the implementation somewhat... Functions whose names end in "_ptr" return pointers to bytes in the page. That memory is persistant; and will eventually be written back to the page file. */ namespace rose { //#define PACK_STATS #ifdef PACK_STATS static unsigned long long pack_exceptionBytes = 0; static unsigned long long pack_colBytes[20]; static unsigned long long pack_pageCount = 0; static int pack_first = 1; #endif /** * A "pageLoaded()" callback function for Stasis' buffer manager. */ template void staticMulticolumnLoaded(Page *p); template , class COMP2 = For, class COMP3=For, class COMP4=For, class COMP5=For, class COMP6=For, class COMP7=For, class COMP8=For, class COMP9=For, class COMP10=For, class COMP11 = For, class COMP12 = For, class COMP13=For, class COMP14=For, class COMP15=For, class COMP16=For, class COMP17=For, class COMP18=For, class COMP19=For > class StaticMulticolumn { public: static page_impl impl(); static const plugin_id_t PAGE_FORMAT_ID = 1; typedef TUPLE TUP; typedef COMP0 CMP0; typedef COMP1 CMP1; typedef COMP2 CMP2; typedef COMP3 CMP3; typedef COMP4 CMP4; typedef COMP5 CMP5; typedef COMP6 CMP6; typedef COMP7 CMP7; typedef COMP8 CMP8; typedef COMP9 CMP9; typedef COMP10 CMP10; typedef COMP11 CMP11; typedef COMP12 CMP12; typedef COMP13 CMP13; typedef COMP14 CMP14; typedef COMP15 CMP15; typedef COMP16 CMP16; typedef COMP17 CMP17; typedef COMP18 CMP18; typedef COMP19 CMP19; StaticMulticolumn(int xid, Page *p) : p_(p), first_exception_byte_(0), unpacked_(1) { stasis_page_cleanup(p); *column_count_ptr() = N; bytes_left_ = first_header_byte_ptr()- p->memAddr; first_exception_byte_ = first_header_byte_ptr() - p_->memAddr; #define STATIC_MC_INIT(i,typ,cmp) \ if(i < N) { \ columns_[i] = new byte[USABLE_SIZE_OF_PAGE]; \ cmp = new typ(xid,(void*)columns_[i]); \ cmp->init_mem(columns_[i]); \ *column_plugin_id_ptr(i) = cmp->PLUGIN_ID; \ bytes_left_ -= (cmp->bytes_used() + cmp->max_overrun()); \ } STATIC_MC_INIT(0, CMP0, plugin0) STATIC_MC_INIT(1, CMP1, plugin1) STATIC_MC_INIT(2, CMP2, plugin2) ; STATIC_MC_INIT(3, CMP3, plugin3) STATIC_MC_INIT(4, CMP4, plugin4) STATIC_MC_INIT(5, CMP5, plugin5) ; STATIC_MC_INIT(6, CMP6, plugin6) STATIC_MC_INIT(7, CMP7, plugin7) STATIC_MC_INIT(8, CMP8, plugin8) ; STATIC_MC_INIT(9, CMP9, plugin9); STATIC_MC_INIT(10, CMP10, plugin10) STATIC_MC_INIT(11, CMP11, plugin11) STATIC_MC_INIT(12, CMP12, plugin12) ; STATIC_MC_INIT(13, CMP13, plugin13) STATIC_MC_INIT(14, CMP14, plugin14) STATIC_MC_INIT(15, CMP15, plugin15) ; STATIC_MC_INIT(16, CMP16, plugin16) STATIC_MC_INIT(17, CMP17, plugin17) STATIC_MC_INIT(18, CMP18, plugin18) ; STATIC_MC_INIT(19, CMP19, plugin19); #undef STATIC_MC_INIT *stasis_page_type_ptr(p) = plugin_id(); p->impl = this; } ~StaticMulticolumn() { #define STATIC_MC_DEINIT(i,plug) \ if(i < N) { \ if(unpacked_) delete [] columns_[i]; \ delete plug; \ } STATIC_MC_DEINIT(0,plugin0); STATIC_MC_DEINIT(1,plugin1); STATIC_MC_DEINIT(2,plugin2); STATIC_MC_DEINIT(3,plugin3); STATIC_MC_DEINIT(4,plugin4); STATIC_MC_DEINIT(5,plugin5); STATIC_MC_DEINIT(6,plugin6); STATIC_MC_DEINIT(7,plugin7); STATIC_MC_DEINIT(8,plugin8); STATIC_MC_DEINIT(9,plugin9); STATIC_MC_DEINIT(10,plugin10); STATIC_MC_DEINIT(11,plugin11); STATIC_MC_DEINIT(12,plugin12); STATIC_MC_DEINIT(13,plugin13); STATIC_MC_DEINIT(14,plugin14); STATIC_MC_DEINIT(15,plugin15); STATIC_MC_DEINIT(16,plugin16); STATIC_MC_DEINIT(17,plugin17); STATIC_MC_DEINIT(18,plugin18); STATIC_MC_DEINIT(19,plugin19); } /* * @return the compressor used for a column. The nature of the mapping between table region and compressor instance is implementation defined, but there will never be more than one compressor per-column, per-page. @param col The column whose compressor should be returned. @return A pointer to a compressor. This pointer is guaranteed to be valid until the next call to this Multicolumn object. After that, the pointer returned here is invalid. */ // void* compressor(column_number_t col) { // XXX return dispatcher_.compressor(col); // } COMP0 * compressor0() const { return plugin0; } COMP1 * compressor1() const { return plugin1; } COMP2 * compressor2() const { return plugin2; } COMP3 * compressor3() const { return plugin3; } COMP4 * compressor4() const { return plugin4; } COMP5 * compressor5() const { return plugin5; } COMP6 * compressor6() const { return plugin6; } COMP7 * compressor7() const { return plugin7; } COMP8 * compressor8() const { return plugin8; } COMP9 * compressor9() const { return plugin9; } COMP10 * compressor10() const { return plugin10; } COMP11 * compressor11() const { return plugin11; } COMP12 * compressor12() const { return plugin12; } COMP13 * compressor13() const { return plugin13; } COMP14 * compressor14() const { return plugin14; } COMP15 * compressor15() const { return plugin15; } COMP16 * compressor16() const { return plugin16; } COMP17 * compressor17() const { return plugin17; } COMP18 * compressor18() const { return plugin18; } COMP19 * compressor19() const { return plugin19; } inline slot_index_t append(int xid, TUPLE const & dat) { slot_index_t ret = 0; slot_index_t newret = 0; if(0 < N) ret = plugin0->append(xid, *dat.get0(),&first_exception_byte_, p_->memAddr, &bytes_left_); // if(bytes_left_ >= 0) { if(1 < N) newret = plugin1->append(xid, *dat.get1(),&first_exception_byte_, p_->memAddr, &bytes_left_); // if(bytes_left_ >= 0) { // assert(newret == ret); if(2 < N) newret = plugin2->append(xid, *dat.get2(),&first_exception_byte_, p_->memAddr, &bytes_left_); // if(bytes_left_ >= 0) { // assert(newret == ret); if(3 < N) newret = plugin3->append(xid, *dat.get3(),&first_exception_byte_, p_->memAddr, &bytes_left_); // if(bytes_left_ >= 0) { // assert(newret == ret); if(4 < N) newret = plugin4->append(xid, *dat.get4(),&first_exception_byte_, p_->memAddr, &bytes_left_); // if(bytes_left_ >= 0) { // assert(newret == ret); if(5 < N) newret = plugin5->append(xid, *dat.get5(),&first_exception_byte_, p_->memAddr, &bytes_left_); // if(bytes_left_ >= 0) { // assert(newret == ret); if(6 < N) newret = plugin6->append(xid, *dat.get6(),&first_exception_byte_, p_->memAddr, &bytes_left_); // if(bytes_left_ >= 0) { // assert(newret == ret); if(7 < N) newret = plugin7->append(xid, *dat.get7(),&first_exception_byte_, p_->memAddr, &bytes_left_); // if(bytes_left_ >= 0) { // assert(newret == ret); if(8 < N) newret = plugin8->append(xid, *dat.get8(),&first_exception_byte_, p_->memAddr, &bytes_left_); // if(bytes_left_ >= 0) { // assert(newret == ret); if(9 < N) newret = plugin9->append(xid, *dat.get9(),&first_exception_byte_, p_->memAddr, &bytes_left_); // }}}}}}}}} if(10 < N) newret = plugin10->append(xid, *dat.get10(),&first_exception_byte_, p_->memAddr, &bytes_left_); // if(bytes_left_ >= 0) { if(11 < N) newret = plugin11->append(xid, *dat.get11(),&first_exception_byte_, p_->memAddr, &bytes_left_); // if(bytes_left_ >= 0) { // assert(newret == ret); if(12 < N) newret = plugin12->append(xid, *dat.get12(),&first_exception_byte_, p_->memAddr, &bytes_left_); // if(bytes_left_ >= 0) { // assert(newret == ret); if(13 < N) newret = plugin13->append(xid, *dat.get13(),&first_exception_byte_, p_->memAddr, &bytes_left_); // if(bytes_left_ >= 0) { // assert(newret == ret); if(14 < N) newret = plugin14->append(xid, *dat.get14(),&first_exception_byte_, p_->memAddr, &bytes_left_); // if(bytes_left_ >= 0) { // assert(newret == ret); if(15 < N) newret = plugin15->append(xid, *dat.get15(),&first_exception_byte_, p_->memAddr, &bytes_left_); // if(bytes_left_ >= 0) { // assert(newret == ret); if(16 < N) newret = plugin16->append(xid, *dat.get16(),&first_exception_byte_, p_->memAddr, &bytes_left_); // if(bytes_left_ >= 0) { // assert(newret == ret); if(17 < N) newret = plugin17->append(xid, *dat.get17(),&first_exception_byte_, p_->memAddr, &bytes_left_); // if(bytes_left_ >= 0) { // assert(newret == ret); if(18 < N) newret = plugin18->append(xid, *dat.get18(),&first_exception_byte_, p_->memAddr, &bytes_left_); // if(bytes_left_ >= 0) { // assert(newret == ret); if(19 < N) newret = plugin19->append(xid, *dat.get19(),&first_exception_byte_, p_->memAddr, &bytes_left_); // }}}}}}}}} // assert(N == 1 || bytes_left_ < 0 || newret == ret); return (bytes_left_ < 0) ? NOSPACE : ret; } inline TUPLE * recordRead(int xid, slot_index_t slot, TUPLE * buf) { bool ret = 1; if(0 < N) ret = plugin0->recordRead(xid,slot,p_->memAddr,const_cast(buf->get0())) ? ret : 0; if(1 < N) ret = plugin1->recordRead(xid,slot,p_->memAddr,const_cast(buf->get1())) ? ret : 0; if(2 < N) ret = plugin2->recordRead(xid,slot,p_->memAddr,const_cast(buf->get2())) ? ret : 0; if(3 < N) ret = plugin3->recordRead(xid,slot,p_->memAddr,const_cast(buf->get3())) ? ret : 0; if(4 < N) ret = plugin4->recordRead(xid,slot,p_->memAddr,const_cast(buf->get4())) ? ret : 0; if(5 < N) ret = plugin5->recordRead(xid,slot,p_->memAddr,const_cast(buf->get5())) ? ret : 0; if(6 < N) ret = plugin6->recordRead(xid,slot,p_->memAddr,const_cast(buf->get6())) ? ret : 0; if(7 < N) ret = plugin7->recordRead(xid,slot,p_->memAddr,const_cast(buf->get7())) ? ret : 0; if(8 < N) ret = plugin8->recordRead(xid,slot,p_->memAddr,const_cast(buf->get8())) ? ret : 0; if(9 < N) ret = plugin9->recordRead(xid,slot,p_->memAddr,const_cast(buf->get9())) ? ret : 0; if(10 < N) ret = plugin10->recordRead(xid,slot,p_->memAddr,const_cast(buf->get10())) ? ret : 0; if(11 < N) ret = plugin11->recordRead(xid,slot,p_->memAddr,const_cast(buf->get11())) ? ret : 0; if(12 < N) ret = plugin12->recordRead(xid,slot,p_->memAddr,const_cast(buf->get12())) ? ret : 0; if(13 < N) ret = plugin13->recordRead(xid,slot,p_->memAddr,const_cast(buf->get13())) ? ret : 0; if(14 < N) ret = plugin14->recordRead(xid,slot,p_->memAddr,const_cast(buf->get14())) ? ret : 0; if(15 < N) ret = plugin15->recordRead(xid,slot,p_->memAddr,const_cast(buf->get15())) ? ret : 0; if(16 < N) ret = plugin16->recordRead(xid,slot,p_->memAddr,const_cast(buf->get16())) ? ret : 0; if(17 < N) ret = plugin17->recordRead(xid,slot,p_->memAddr,const_cast(buf->get17())) ? ret : 0; if(18 < N) ret = plugin18->recordRead(xid,slot,p_->memAddr,const_cast(buf->get18())) ? ret : 0; if(19 < N) ret = plugin19->recordRead(xid,slot,p_->memAddr,const_cast(buf->get19())) ? ret : 0; return ret ? buf : 0; } inline slot_index_t recordCount(int xid) { slot_index_t recordCount; slot_index_t c; // XXX memoize this function if(0 < N) recordCount = plugin0->recordCount(); if(1 < N) { c = plugin1->recordCount(); recordCount = recordCount > c ? c :recordCount; } if(2 < N) { c = plugin2->recordCount(); recordCount = recordCount > c ? c :recordCount; } if(3 < N) { c = plugin3->recordCount(); recordCount = recordCount > c ? c :recordCount; } if(4 < N) { c = plugin4->recordCount(); recordCount = recordCount > c ? c :recordCount; } if(5 < N) { c = plugin5->recordCount(); recordCount = recordCount > c ? c :recordCount; } if(6 < N) { c = plugin6->recordCount(); recordCount = recordCount > c ? c :recordCount; } if(7 < N) { c = plugin7->recordCount(); recordCount = recordCount > c ? c :recordCount; } if(8 < N) { c = plugin8->recordCount(); recordCount = recordCount > c ? c :recordCount; } if(9 < N) { c = plugin9->recordCount(); recordCount = recordCount > c ? c :recordCount; } if(10 < N) { c = plugin10->recordCount(); recordCount = recordCount > c ? c :recordCount; } if(11 < N) { c = plugin11->recordCount(); recordCount = recordCount > c ? c :recordCount; } if(12 < N) { c = plugin12->recordCount(); recordCount = recordCount > c ? c :recordCount; } if(13 < N) { c = plugin13->recordCount(); recordCount = recordCount > c ? c :recordCount; } if(14 < N) { c = plugin14->recordCount(); recordCount = recordCount > c ? c :recordCount; } if(15 < N) { c = plugin15->recordCount(); recordCount = recordCount > c ? c :recordCount; } if(16 < N) { c = plugin16->recordCount(); recordCount = recordCount > c ? c :recordCount; } if(17 < N) { c = plugin17->recordCount(); recordCount = recordCount > c ? c :recordCount; } if(18 < N) { c = plugin18->recordCount(); recordCount = recordCount > c ? c :recordCount; } if(19 < N) { c = plugin19->recordCount(); recordCount = recordCount > c ? c :recordCount; } return recordCount; } /* inline slot_index_t recordCount(int xid) { if(1 == N) return plugin0->recordCount(xid); if(2 == N) return plugin1->recordCount(xid); if(3 == N) return plugin2->recordCount(xid); if(4 == N) return plugin3->recordCount(xid); if(5 == N) return plugin4->recordCount(xid); if(6 == N) return plugin5->recordCount(xid); if(7 == N) return plugin6->recordCount(xid); if(8 == N) return plugin7->recordCount(xid); if(9 == N) return plugin8->recordCount(xid); if(10 == N) return plugin9->recordCount(xid); abort(); } */ inline TUPLE * recordFind(int xid, TUPLE& val, TUPLE& scratch) { std::pair pair_scratch; std::pair * ret; // printf("static multiclumn record find\n"); fflush(stdout); if(0 < N) ret = plugin0->recordFind(xid, 0, recordCount(xid), p_->memAddr, *val.get0(), pair_scratch); //assert(ret); if(1 < N) if(ret) ret = plugin1->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get1(), pair_scratch); //assert(ret); if(2 < N) if(ret) ret = plugin2->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get2(), pair_scratch); //assert(ret); if(3 < N) if(ret) ret = plugin3->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get3(), pair_scratch); //assert(ret); if(4 < N) if(ret) ret = plugin4->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get4(), pair_scratch); //assert(ret); if(5 < N) if(ret) ret = plugin5->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get5(), pair_scratch); //assert(ret); if(6 < N) if(ret) ret = plugin6->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get6(), pair_scratch); //assert(ret); if(7 < N) if(ret) ret = plugin7->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get7(), pair_scratch); //assert(ret); if(8 < N) if(ret) ret = plugin8->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get8(), pair_scratch); //assert(ret); if(9 < N) if(ret) ret = plugin9->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get9(), pair_scratch); //assert(ret); if(10 < N) if(ret) ret = plugin10->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get10(), pair_scratch); //assert(ret); if(11 < N) if(ret) ret = plugin11->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get11(), pair_scratch); //assert(ret); if(12 < N) if(ret) ret = plugin12->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get12(), pair_scratch); //assert(ret); if(13 < N) if(ret) ret = plugin13->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get13(), pair_scratch); //assert(ret); if(14 < N) if(ret) ret = plugin14->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get14(), pair_scratch); //assert(ret); if(15 < N) if(ret) ret = plugin15->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get15(), pair_scratch); //assert(ret); if(16 < N) if(ret) ret = plugin16->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get16(), pair_scratch); //assert(ret); if(17 < N) if(ret) ret = plugin17->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get17(), pair_scratch); //assert(ret); if(18 < N) if(ret) ret = plugin18->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get18(), pair_scratch); //assert(ret); if(19 < N) if(ret) ret = plugin19->recordFind(xid, ret->first, ret->second, p_->memAddr, *val.get19(), pair_scratch); //assert(ret); if(ret) { // XXX slow, doesn't return whole range... recordRead(xid, ret->first, &scratch); return &scratch; } else { return 0; } } inline void pack() { #ifdef PACK_STATS if(pack_first) { pack_exceptionBytes = 0; pack_pageCount = 0; for(int i = 0; i < N; i++) { pack_colBytes[i] = 0; } pack_first = 0; } #define updateColStats(i, comp) \ pack_colBytes[i] += comp->bytes_used() #else #define updateColStats(i, comp) #endif byte_off_t first_free = 0; byte_off_t last_free = (intptr_t)(first_header_byte_ptr() - p_->memAddr); if(unpacked_) { *exceptions_len_ptr() = last_free - first_exception_byte_; last_free -= *exceptions_len_ptr(); *exceptions_offset_ptr() = last_free; #ifdef PACK_STATS pack_pageCount++; pack_exceptionBytes += *exceptions_len_ptr(); if(0 == ((pack_pageCount+1) % 1000)) { printf("%lld pages; %lld exception bytes cols: {", pack_pageCount, pack_exceptionBytes); for(int i = 0; i < N; i++) { printf("%lld, ", pack_colBytes[i]); } printf("}\n"); } #endif #define STATIC_MC_PACK(i,comp) \ if(i < N) { \ updateColStats(i,comp); \ *column_offset_ptr(i) = first_free; \ byte_off_t bytes_used = comp->bytes_used(); \ memcpy(column_base_ptr(i), columns_[i], bytes_used); \ first_free += bytes_used; \ assert(first_free <= last_free); \ delete [] columns_[i]; \ columns_[i] = column_base_ptr(i); \ comp->mem(columns_[i]); \ } STATIC_MC_PACK(0,plugin0) STATIC_MC_PACK(1,plugin1) ; STATIC_MC_PACK(2,plugin2) STATIC_MC_PACK(3,plugin3) ; STATIC_MC_PACK(4,plugin4) STATIC_MC_PACK(5,plugin5) ; STATIC_MC_PACK(6,plugin6) STATIC_MC_PACK(7,plugin7) ; STATIC_MC_PACK(8,plugin8) STATIC_MC_PACK(9,plugin9) ; STATIC_MC_PACK(10,plugin10) STATIC_MC_PACK(11,plugin11) ; STATIC_MC_PACK(12,plugin12) STATIC_MC_PACK(13,plugin13) ; STATIC_MC_PACK(14,plugin14) STATIC_MC_PACK(15,plugin15) ; STATIC_MC_PACK(16,plugin16) STATIC_MC_PACK(17,plugin17) ; STATIC_MC_PACK(18,plugin18) STATIC_MC_PACK(19,plugin19) ; #undef STATIC_MC_PACK unpacked_ = 0; } } private: COMP0* plugin0; COMP1* plugin1; COMP2* plugin2; COMP3* plugin3; COMP4* plugin4; COMP5* plugin5; COMP6* plugin6; COMP7* plugin7; COMP8* plugin8; COMP9* plugin9; COMP10* plugin10; COMP11* plugin11; COMP12* plugin12; COMP13* plugin13; COMP14* plugin14; COMP15* plugin15; COMP16* plugin16; COMP17* plugin17; COMP18* plugin18; COMP19* plugin19; typedef struct column_header { byte_off_t off; plugin_id_t plugin_id; } column_header; /** Load an existing multicolumn Page */ StaticMulticolumn(Page * p) : p_(p), first_exception_byte_(*exceptions_offset_ptr()), unpacked_(0) { byte_off_t first_free = 0; assert(N == *column_count_ptr()); #define STATIC_MC_INIT(i,plug,cmp) \ if(i < N) { \ columns_[i] = p_->memAddr + *column_offset_ptr(i); \ plug = new cmp((void*)columns_[i]); \ first_free = *column_offset_ptr(i) + plug->bytes_used(); \ } STATIC_MC_INIT(0, plugin0,COMP0) ; STATIC_MC_INIT(1, plugin1,COMP1) ; STATIC_MC_INIT(2, plugin2,COMP2) ; STATIC_MC_INIT(3, plugin3,COMP3) ; STATIC_MC_INIT(4, plugin4,COMP4) ; STATIC_MC_INIT(5, plugin5,COMP5) ; STATIC_MC_INIT(6, plugin6,COMP6) ; STATIC_MC_INIT(7, plugin7,COMP7) ; STATIC_MC_INIT(8, plugin8,COMP8) ; STATIC_MC_INIT(9, plugin9,COMP9) ; STATIC_MC_INIT(10, plugin10,COMP10) ; STATIC_MC_INIT(11, plugin11,COMP11) ; STATIC_MC_INIT(12, plugin12,COMP12) ; STATIC_MC_INIT(13, plugin13,COMP13) ; STATIC_MC_INIT(14, plugin14,COMP14) ; STATIC_MC_INIT(15, plugin15,COMP15) ; STATIC_MC_INIT(16, plugin16,COMP16) ; STATIC_MC_INIT(17, plugin17,COMP17) ; STATIC_MC_INIT(18, plugin18,COMP18) ; STATIC_MC_INIT(19, plugin19,COMP19) ; #undef STATIC_MC_INIT assert(first_free <= *exceptions_offset_ptr()); assert(first_exception_byte_ <= USABLE_SIZE_OF_PAGE); bytes_left_ = *exceptions_offset_ptr() - first_free; assert(*stasis_page_type_ptr(p) == (plugin_id())); } /** The following functions perform pointer arithmetic. This code is performance critical. These short, inlined functions mostly perform simple arithmetic expression involving constants. g++'s optimizer seems to combine and simplify these expressions for us. See the page layout diagram at the top of this file for an explanation of where these pointers are stored */ inline column_number_t * column_count_ptr() { return reinterpret_cast(p_->memAddr+USABLE_SIZE_OF_PAGE)-1; } inline byte_off_t * exceptions_offset_ptr() { return reinterpret_cast(column_count_ptr())-1; } inline byte_off_t * exceptions_len_ptr() { return exceptions_offset_ptr()-1;; } inline column_header * column_header_ptr(column_number_t column_number) { return reinterpret_cast(exceptions_len_ptr())-(1+column_number); } inline byte_off_t * column_offset_ptr(column_number_t column_number) { return &(column_header_ptr(column_number)->off); } /** This stores the plugin_id associated with this page's compressor. @see rose::plugin_id() */ inline plugin_id_t * column_plugin_id_ptr(column_number_t column_number) { return &(column_header_ptr(column_number)->plugin_id); } /** The first byte that contains data for this column. The length of the column data can be determined by calling COMPRESSOR's bytes_used() member function. (PluginDispatcher can handle this). */ inline byte * column_base_ptr(column_number_t column_number) { return *column_offset_ptr(column_number) + p_->memAddr; } inline byte * first_header_byte_ptr() { return reinterpret_cast(column_header_ptr((*column_count_ptr())-1)); } static inline plugin_id_t plugin_id() { // XXX collides with multicolumn.h return USER_DEFINED_PAGE(0) + 32 + TUPLE::TUPLE_ID; } Page * p_; byte * columns_[N]; byte_off_t first_exception_byte_; int bytes_left_; int unpacked_; friend void staticMulticolumnLoaded < N,TUPLE,COMP0,COMP1,COMP2,COMP3,COMP4,COMP5,COMP6,COMP7,COMP8,COMP9, COMP10,COMP11,COMP12,COMP13,COMP14,COMP15,COMP16,COMP17,COMP18,COMP19 >(Page *p); }; /// End performance-critical code --------------------------------------------- /// Stuff below this line interfaces with Stasis' buffer manager -------------- /** Basic page_impl for multicolumn pages @see stasis/page.h and pstar-impl.h */ static const page_impl static_multicolumn_impl = { -1, 0, // multicolumnRead, 0, // multicolumnWrite, 0, // multicolumnReadDone, 0, // multicolumnWriteDone, 0, // multicolumnGetType, 0, // multicolumnSetType, 0, // multicolumnGetLength, 0, // multicolumnFirst, 0, // multicolumnNext, 0, // multicolumnIsBlockSupported, 0, // multicolumnBlockFirst, 0, // multicolumnBlockNext, 0, // multicolumnBlockDone, 0, // multicolumnFreespace, 0, // multicolumnCompact, 0, // multicolumnPreRalloc, 0, // multicolumnPostRalloc, 0, // multicolumnFree, 0, // dereference_identity, 0, // multicolumnLoaded, 0, // multicolumnFlushed 0, // multicolumnCleanup }; template void staticMulticolumnLoaded(Page *p) { p->LSN = *stasis_page_lsn_ptr(p); p->impl = new StaticMulticolumn(p); } template static void staticMulticolumnFlushed(Page *p) { *stasis_page_lsn_ptr(p) = p->LSN; ((StaticMulticolumn*)(p->impl))->pack(); } template static void staticMulticolumnCleanup(Page *p) { delete (StaticMulticolumn*)p->impl; p->impl = 0; } template page_impl StaticMulticolumn::impl() { page_impl ret = static_multicolumn_impl; ret.page_type = StaticMulticolumn::plugin_id(); ret.pageLoaded = staticMulticolumnLoaded; ret.pageFlushed = staticMulticolumnFlushed; ret.pageCleanup = staticMulticolumnCleanup; return ret; } } // namespace rose #endif // _ROSE_COMPRESSION_STATIC_MULTICOLUMN_H__