Fairport
v1.0.38
|
00001 00002 00003 00004 00005 00006 #ifndef FAIRPORT_LTP_TABLE_H 00007 #define FAIRPORT_LTP_TABLE_H 00008 00009 #include <vector> 00010 #if __GNUC__ 00011 # include <tr1/unordered_map> 00012 #else 00013 # include <unordered_map> 00014 #endif 00015 #include <boost/iterator/iterator_facade.hpp> 00016 00017 #include "fairport/util/primitives.h" 00018 00019 #include "fairport/ndb/node.h" 00020 00021 #include "fairport/ltp/object.h" 00022 #include "fairport/ltp/heap.h" 00023 00024 namespace fairport 00025 { 00026 00027 class table_impl; 00029 00030 typedef std::tr1::shared_ptr<table_impl> table_ptr; 00031 typedef std::tr1::shared_ptr<const table_impl> const_table_ptr; 00033 00037 table_ptr open_table(const node& n); 00038 00049 class const_table_row : public const_property_object 00050 { 00051 public: 00054 const_table_row(const const_table_row& other) 00055 : m_position(other.m_position), m_table(other.m_table) { } 00059 const_table_row(ulong position, const const_table_ptr& table) 00060 : m_position(position), m_table(table) { } 00061 00064 row_id get_row_id() const; 00065 00066 // const_property_object 00067 std::vector<prop_id> get_prop_list() const; 00068 prop_type get_prop_type(prop_id id) const; 00069 bool prop_exists(prop_id id) const; 00070 size_t size(prop_id id) const; 00071 hnid_stream_device open_prop_stream(prop_id id); 00072 00073 private: 00074 // const_property_object 00075 byte get_value_1(prop_id id) const; 00076 ushort get_value_2(prop_id id) const; 00077 ulong get_value_4(prop_id id) const; 00078 ulonglong get_value_8(prop_id id) const; 00079 std::vector<byte> get_value_variable(prop_id id) const; 00080 00081 ulong m_position; 00082 const_table_ptr m_table; 00083 }; 00084 00092 class const_table_row_iter : public boost::iterator_facade<const_table_row_iter, const_table_row, boost::random_access_traversal_tag, const_table_row> 00093 { 00094 public: 00096 const_table_row_iter() 00097 : m_position(0) { } 00098 00102 const_table_row_iter(ulong pos, const const_table_ptr& table) 00103 : m_position(pos), m_table(table) { } 00104 00105 private: 00106 friend class boost::iterator_core_access; 00107 00108 void increment() { ++m_position; } 00109 bool equal(const const_table_row_iter& other) const 00110 { return ((m_position == other.m_position) && (m_table == other.m_table)); } 00111 const_table_row dereference() const 00112 { return const_table_row(m_position, m_table); } 00113 void decrement() { --m_position; } 00114 void advance(int off) { m_position += off; } 00115 size_t distance_to(const const_table_row_iter& other) const 00116 { return (other.m_position - m_position); } 00117 00118 ulong m_position; 00119 const_table_ptr m_table; 00120 }; 00121 00136 class table_impl : public std::tr1::enable_shared_from_this<table_impl> 00137 { 00138 public: 00139 virtual ~table_impl() { } 00144 virtual ulong lookup_row(row_id id) const = 0; 00145 00149 const_table_row operator[](ulong row) const 00150 { return const_table_row(row, shared_from_this()); } 00153 const_table_row_iter begin() const 00154 { return const_table_row_iter(0, shared_from_this()); } 00157 const_table_row_iter end() const 00158 { return const_table_row_iter(size(), shared_from_this()); } 00159 00162 virtual node& get_node() = 0; 00165 virtual const node& get_node() const = 0; 00172 virtual ulonglong get_cell_value(ulong row, prop_id id) const = 0; 00179 virtual std::vector<byte> read_cell(ulong row, prop_id id) const = 0; 00187 virtual hnid_stream_device open_cell_stream(ulong row, prop_id id) = 0; 00194 virtual std::vector<prop_id> get_prop_list() const = 0; 00197 virtual prop_type get_prop_type(prop_id id) const = 0; 00203 virtual row_id get_row_id(ulong row) const = 0; 00206 virtual size_t size() const = 0; 00211 virtual bool prop_exists(ulong row, prop_id id) const = 0; 00217 virtual size_t row_prop_size(ulong row, prop_id id) const = 0; 00218 }; 00219 00233 class empty_table : public table_impl 00234 { 00235 public: 00236 node& get_node() 00237 { throw key_not_found<node_id>(0); } 00238 const node& get_node() const 00239 { throw key_not_found<node_id>(0); } 00240 ulong lookup_row(row_id id) const 00241 { throw key_not_found<row_id>(id); } 00242 ulonglong get_cell_value(ulong row, prop_id) const 00243 { throw key_not_found<ulong>(row); } 00244 std::vector<byte> read_cell(ulong row, prop_id) const 00245 { throw key_not_found<ulong>(row); } 00246 hnid_stream_device open_cell_stream(ulong row, prop_id) 00247 { throw key_not_found<ulong>(row); } 00248 std::vector<prop_id> get_prop_list() const 00249 { return std::vector<prop_id>(); } 00250 prop_type get_prop_type(prop_id id) const 00251 { throw key_not_found<prop_id>(id); } 00252 row_id get_row_id(ulong row) const 00253 { throw key_not_found<ulong>(row); } 00254 size_t size() const 00255 { return 0; } 00256 bool prop_exists(ulong row, prop_id) const 00257 { throw key_not_found<ulong>(row); } 00258 size_t row_prop_size(ulong row, prop_id) const 00259 { throw key_not_found<ulong>(row); } 00260 }; 00261 00276 template<typename T> 00277 class basic_table : public table_impl 00278 { 00279 public: 00280 node& get_node() 00281 { return m_prows->get_node(); } 00282 const node& get_node() const 00283 { return m_prows->get_node(); } 00284 ulong lookup_row(row_id id) const; 00285 ulonglong get_cell_value(ulong row, prop_id id) const; 00286 std::vector<byte> read_cell(ulong row, prop_id id) const; 00287 hnid_stream_device open_cell_stream(ulong row, prop_id id); 00288 std::vector<prop_id> get_prop_list() const; 00289 prop_type get_prop_type(prop_id id) const; 00290 row_id get_row_id(ulong row) const; 00291 size_t size() const; 00292 bool prop_exists(ulong row, prop_id id) const; 00293 size_t row_prop_size(ulong row, prop_id id) const; 00294 00295 private: 00296 friend table_ptr open_table(const node& n); 00297 basic_table(const node& n); 00298 00299 std::tr1::shared_ptr<bth_node<row_id, T> > m_prows; 00300 00301 // only one of the following two items is valid 00302 std::vector<byte> m_vec_rowarray; 00303 std::tr1::shared_ptr<node> m_pnode_rowarray; 00304 00305 std::tr1::unordered_map<prop_id, disk::column_description> m_columns; 00306 typedef std::tr1::unordered_map<prop_id, disk::column_description>::iterator column_iter; 00307 typedef std::tr1::unordered_map<prop_id, disk::column_description>::const_iterator const_column_iter; 00308 00309 ushort m_offsets[disk::tc_offsets_max]; 00310 00311 // helper functions 00314 ulong cb_per_row() const { return m_offsets[disk::tc_offsets_bitmap]; } 00317 ulong exists_bitmap_start() const { return m_offsets[disk::tc_offsets_one]; } 00320 ulong rows_per_page() const { return (m_pnode_rowarray ? m_pnode_rowarray->get_page_size(0) / cb_per_row() : m_vec_rowarray.size() / cb_per_row()); } 00325 template<typename Val> Val read_raw_row(ulong row, ushort offset) const; 00328 std::vector<byte> read_exists_bitmap(ulong row) const; 00329 }; 00330 00331 typedef basic_table<ushort> small_table; 00332 typedef basic_table<ulong> large_table; 00333 00346 class table 00347 { 00348 public: 00349 00351 table() 00352 : m_ptable(new empty_table()) { } 00353 00356 explicit table(const node& n); 00359 table(const table& other) 00360 : m_ptable(other.m_ptable) { } 00361 00363 const_table_row operator[](ulong row) const 00364 { return (*m_ptable)[row]; } 00366 const_table_row_iter begin() const 00367 { return m_ptable->begin(); } 00369 const_table_row_iter end() const 00370 { return m_ptable->end(); } 00371 00373 node& get_node() 00374 { return m_ptable->get_node(); } 00376 const node& get_node() const 00377 { return m_ptable->get_node(); } 00379 ulonglong get_cell_value(ulong row, prop_id id) const 00380 { return m_ptable->get_cell_value(row, id); } 00382 std::vector<byte> read_cell(ulong row, prop_id id) const 00383 { return m_ptable->read_cell(row, id); } 00385 hnid_stream_device open_cell_stream(ulong row, prop_id id) 00386 { return m_ptable->open_cell_stream(row, id); } 00388 std::vector<prop_id> get_prop_list() const 00389 { return m_ptable->get_prop_list(); } 00391 prop_type get_prop_type(prop_id id) const 00392 { return m_ptable->get_prop_type(id); } 00394 row_id get_row_id(ulong row) const 00395 { return m_ptable->get_row_id(row); } 00397 ulong lookup_row(row_id id) const 00398 { return m_ptable->lookup_row(id); } 00400 size_t size() const 00401 { return m_ptable->size(); } 00402 00403 private: 00404 table_ptr m_ptable; 00405 }; 00406 00407 } // end fairport namespace 00408 00409 inline fairport::table_ptr fairport::open_table(const node& n) 00410 { 00411 if(n.get_id() == nid_all_message_search_contents) 00412 { 00413 throw not_implemented("gust table"); 00414 } 00415 00416 heap h(n); 00417 std::vector<byte> table_info = h.read(h.get_root_id()); 00418 disk::tc_header* pheader = (disk::tc_header*)&table_info[0]; 00419 00420 std::vector<byte> bth_info = h.read(pheader->row_btree_id); 00421 disk::bth_header* pbthheader = (disk::bth_header*)&bth_info[0]; 00422 00423 if(pbthheader->entry_size == 4) 00424 return table_ptr(new large_table(n)); 00425 else 00426 return table_ptr(new small_table(n)); 00427 } 00428 00429 inline std::vector<fairport::prop_id> fairport::const_table_row::get_prop_list() const 00430 { 00431 std::vector<prop_id> columns = m_table->get_prop_list(); 00432 std::vector<prop_id> props; 00433 00434 for(size_t i = 0; i < columns.size(); ++i) 00435 { 00436 if(prop_exists(columns[i])) 00437 props.push_back(columns[i]); 00438 } 00439 00440 return props; 00441 } 00442 00443 inline size_t fairport::const_table_row::size(prop_id id) const 00444 { 00445 return m_table->row_prop_size(m_position, id); 00446 } 00447 00448 inline fairport::prop_type fairport::const_table_row::get_prop_type(prop_id id) const 00449 { 00450 return m_table->get_prop_type(id); 00451 } 00452 00453 inline bool fairport::const_table_row::prop_exists(prop_id id) const 00454 { 00455 return m_table->prop_exists(m_position, id); 00456 } 00457 00458 inline fairport::row_id fairport::const_table_row::get_row_id() const 00459 { 00460 return m_table->get_row_id(m_position); 00461 } 00462 00463 inline fairport::byte fairport::const_table_row::get_value_1(prop_id id) const 00464 { 00465 return (byte)m_table->get_cell_value(m_position, id); 00466 } 00467 00468 inline fairport::ushort fairport::const_table_row::get_value_2(prop_id id) const 00469 { 00470 return (ushort)m_table->get_cell_value(m_position, id); 00471 } 00472 00473 inline fairport::ulong fairport::const_table_row::get_value_4(prop_id id) const 00474 { 00475 return (ulong)m_table->get_cell_value(m_position, id); 00476 } 00477 00478 inline fairport::ulonglong fairport::const_table_row::get_value_8(prop_id id) const 00479 { 00480 return m_table->get_cell_value(m_position, id); 00481 } 00482 00483 inline std::vector<fairport::byte> fairport::const_table_row::get_value_variable(prop_id id) const 00484 { 00485 return m_table->read_cell(m_position, id); 00486 } 00487 00488 inline fairport::hnid_stream_device fairport::const_table_row::open_prop_stream(prop_id id) 00489 { 00490 return (std::tr1::const_pointer_cast<table_impl>(m_table))->open_cell_stream(m_position, id); 00491 } 00492 00493 template<typename T> 00494 inline fairport::basic_table<T>::basic_table(const node& n) 00495 { 00496 heap h(n, disk::heap_sig_tc); 00497 00498 std::vector<byte> table_info = h.read(h.get_root_id()); 00499 disk::tc_header* pheader = (disk::tc_header*)&table_info[0]; 00500 00501 #ifdef FAIRPORT_VALIDATION_LEVEL_WEAK 00502 if(pheader->signature != disk::heap_sig_tc) 00503 throw sig_mismatch("heap_sig_tc expected", 0, n.get_id(), pheader->signature, disk::heap_sig_tc); 00504 #endif 00505 00506 m_prows = h.open_bth<row_id, T>(pheader->row_btree_id); 00507 00508 for(int i = 0; i < pheader->num_columns; ++i) 00509 m_columns[pheader->columns[i].id] = pheader->columns[i]; 00510 00511 for(int i = 0; i < disk::tc_offsets_max; ++i) 00512 m_offsets[i] = pheader->size_offsets[i]; 00513 00514 if(is_subnode_id(pheader->row_matrix_id)) 00515 { 00516 m_pnode_rowarray.reset(new node(n.lookup(pheader->row_matrix_id))); 00517 } 00518 else if(pheader->row_matrix_id) 00519 { 00520 m_vec_rowarray = h.read(pheader->row_matrix_id); 00521 } 00522 } 00523 00524 template<typename T> 00525 inline size_t fairport::basic_table<T>::size() const 00526 { 00527 if(m_pnode_rowarray) 00528 { 00529 return (m_pnode_rowarray->get_page_count()-1) * rows_per_page() + m_pnode_rowarray->get_page_size(m_pnode_rowarray->get_page_count()-1) / cb_per_row(); 00530 } 00531 else 00532 { 00533 return m_vec_rowarray.size() / cb_per_row(); 00534 } 00535 } 00536 00537 template<typename T> 00538 inline std::vector<fairport::prop_id> fairport::basic_table<T>::get_prop_list() const 00539 { 00540 std::vector<prop_id> props; 00541 00542 for(const_column_iter i = m_columns.begin(); i != m_columns.end(); ++i) 00543 props.push_back(i->first); 00544 00545 return props; 00546 } 00547 00548 template<typename T> 00549 inline fairport::ulong fairport::basic_table<T>::lookup_row(row_id id) const 00550 { 00551 try 00552 { 00553 return (ulong)m_prows->lookup(id); 00554 } 00555 catch(key_not_found<T>& e) 00556 { 00557 throw key_not_found<row_id>(e.which()); 00558 } 00559 } 00560 00561 template<typename T> 00562 inline fairport::ulonglong fairport::basic_table<T>::get_cell_value(ulong row, prop_id id) const 00563 { 00564 if(!prop_exists(row, id)) 00565 throw key_not_found<prop_id>(id); 00566 00567 const_column_iter column = m_columns.find(id); 00568 ulonglong value; 00569 00570 switch(column->second.size) 00571 { 00572 case 8: 00573 value = read_raw_row<ulonglong>(row, column->second.offset); 00574 break; 00575 case 4: 00576 value = read_raw_row<ulong>(row, column->second.offset); 00577 break; 00578 case 2: 00579 value = read_raw_row<ushort>(row, column->second.offset); 00580 break; 00581 case 1: 00582 value = read_raw_row<byte>(row, column->second.offset); 00583 break; 00584 default: 00585 throw database_corrupt("get_cell_value: invalid cell size"); 00586 } 00587 00588 return value; 00589 } 00590 00591 template<typename T> 00592 inline size_t fairport::basic_table<T>::row_prop_size(ulong row, prop_id id) const 00593 { 00594 heapnode_id hid = static_cast<heapnode_id>(get_cell_value(row, id)); 00595 00596 if(is_subnode_id(hid)) 00597 return get_node().lookup(hid).size(); 00598 else 00599 return m_prows->get_heap_ptr()->size(hid); 00600 } 00601 00602 template<typename T> 00603 inline std::vector<fairport::byte> fairport::basic_table<T>::read_cell(ulong row, prop_id id) const 00604 { 00605 heapnode_id hid = static_cast<heapnode_id>(get_cell_value(row, id)); 00606 std::vector<byte> buffer; 00607 00608 if(is_subnode_id(hid)) 00609 { 00610 node sub(get_node().lookup(hid)); 00611 buffer.resize(sub.size()); 00612 sub.read(buffer, 0); 00613 } 00614 else 00615 { 00616 buffer = m_prows->get_heap_ptr()->read(hid); 00617 } 00618 return buffer; 00619 } 00620 00621 template<typename T> 00622 inline fairport::hnid_stream_device fairport::basic_table<T>::open_cell_stream(ulong row, prop_id id) 00623 { 00624 heapnode_id hid = static_cast<heapnode_id>(get_cell_value(row, id)); 00625 00626 if(is_subnode_id(hid)) 00627 return get_node().lookup(hid).open_as_stream(); 00628 else 00629 return m_prows->get_heap_ptr()->open_stream(hid); 00630 } 00631 00632 template<typename T> 00633 inline fairport::prop_type fairport::basic_table<T>::get_prop_type(prop_id id) const 00634 { 00635 const_column_iter iter = m_columns.find(id); 00636 00637 if(iter == m_columns.end()) 00638 throw key_not_found<prop_id>(id); 00639 00640 return (prop_type)iter->second.type; 00641 } 00642 00643 template<typename T> 00644 inline fairport::row_id fairport::basic_table<T>::get_row_id(ulong row) const 00645 { 00646 return read_raw_row<row_id>(row, 0); 00647 } 00648 00649 template<typename T> 00650 template<typename Val> 00651 inline Val fairport::basic_table<T>::read_raw_row(ulong row, ushort offset) const 00652 { 00653 if(row >= size()) 00654 throw std::out_of_range("row >= size()"); 00655 00656 if(m_pnode_rowarray) 00657 { 00658 ulong page_num = row / rows_per_page(); 00659 ulong page_offset = (row % rows_per_page()) * cb_per_row(); 00660 00661 return m_pnode_rowarray->read<Val>(page_num, page_offset+offset); 00662 } 00663 else 00664 { 00665 Val val; 00666 memcpy(&val, &m_vec_rowarray[ row * cb_per_row() + offset ], sizeof(Val)); 00667 return val; 00668 } 00669 } 00670 00671 template<typename T> 00672 inline std::vector<fairport::byte> fairport::basic_table<T>::read_exists_bitmap(ulong row) const 00673 { 00674 std::vector<byte> exists_bitmap(cb_per_row() - exists_bitmap_start()); 00675 00676 if(row >= size()) 00677 throw std::out_of_range("row >= size()"); 00678 00679 if(m_pnode_rowarray) 00680 { 00681 ulong page_num = row / rows_per_page(); 00682 ulong page_offset = (row % rows_per_page()) * cb_per_row(); 00683 00684 m_pnode_rowarray->read(exists_bitmap, page_num, page_offset + exists_bitmap_start()); 00685 } 00686 else 00687 { 00688 memcpy(&exists_bitmap[0], &m_vec_rowarray[ row * cb_per_row() + exists_bitmap_start() ], exists_bitmap.size()); 00689 } 00690 00691 return exists_bitmap; 00692 } 00693 00694 template<typename T> 00695 inline bool fairport::basic_table<T>::prop_exists(ulong row, prop_id id) const 00696 { 00697 const_column_iter column = m_columns.find(id); 00698 00699 if(column == m_columns.end()) 00700 return false; 00701 00702 std::vector<byte> exists_map = read_exists_bitmap(row); 00703 00704 return test_bit(&exists_map[0], column->second.bit_offset); 00705 } 00706 00707 inline fairport::table::table(const node& n) 00708 { 00709 m_ptable = open_table(n); 00710 } 00711 #endif