// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_mpi_pntuple #define tools_mpi_pntuple // pntuple = for parallel ntupling. #include #include #include namespace tools { namespace mpi { class pntuple : public tools::wroot::base_pntuple { typedef tools::wroot::base_pntuple parent; public: static tools::uint32 protocol_basket() {return 1;} static tools::uint32 protocol_end_fill() {return 2;} public: pntuple(std::ostream& a_out, bool a_byte_swap,tools::uint32 a_compression, const std::string& a_name,const std::string& a_title,bool a_verbose) :parent(a_out,a_byte_swap,a_compression,a_name,a_title,a_verbose) {} pntuple(std::ostream& a_out,bool a_byte_swap,tools::uint32 a_compression,tools::wroot::seek a_seek_directory, const std::vector& a_basket_sizes,const tools::ntuple_booking& a_bkg,bool a_verbose) :parent(a_out,a_byte_swap,a_compression,a_seek_directory,a_basket_sizes,a_bkg,a_verbose) {} virtual ~pntuple() {} protected: pntuple(const pntuple& a_from):parent(a_from){} pntuple& operator=(const pntuple& a_from){parent::operator=(a_from);return *this;} protected: class basket_add : public virtual tools::wroot::branch::iadd_basket { typedef tools::wroot::branch::iadd_basket parent; public: virtual bool add_basket(tools::wroot::basket& a_basket) { m_mpi.pack_reset(); if(!m_mpi.pack(protocol_basket())) return false; if(!m_mpi.pack(m_icol)) return false; if(!m_mpi.spack(a_basket.object_name())) return false; if(!m_mpi.spack(a_basket.object_title())) return false; if(!m_mpi.pack(a_basket.last())) return false; if(!m_mpi.pack(a_basket.nev_buf_size())) return false; if(!m_mpi.pack(a_basket.nev())) return false; if(a_basket.entry_offset()) { if(!m_mpi.bpack(true)) return false; if(!m_mpi.pack(a_basket.nev_buf_size(),a_basket.entry_offset())) return false; } else { if(!m_mpi.bpack(false)) return false; } if(a_basket.displacement()) { if(!m_mpi.bpack(true)) return false; if(!m_mpi.pack(a_basket.nev_buf_size(),a_basket.displacement())) return false; } else { if(!m_mpi.bpack(false)) return false; } if(!m_mpi.pack(a_basket.datbuf().length(),a_basket.datbuf().buf())) return false; if(!m_mpi.send_buffer(m_dest,m_tag)) return false; return true; } public: basket_add(file& a_file,tools::impi& a_mpi,int a_dest,int a_tag,tools::uint32 a_icol) :m_file(a_file),m_mpi(a_mpi),m_dest(a_dest),m_tag(a_tag),m_icol(a_icol) {} protected: basket_add(const basket_add& a_from):parent() ,m_file(a_from.m_file),m_mpi(a_from.m_mpi),m_dest(a_from.m_dest),m_tag(a_from.m_tag),m_icol(a_from.m_icol) {} basket_add& operator=(const basket_add& a_from){ m_file = a_from.m_file; m_dest = a_from.m_dest; m_tag = a_from.m_tag; m_icol = a_from.m_icol; return *this; } protected: file m_file; tools::impi& m_mpi; int m_dest; int m_tag; tools::uint32 m_icol; }; public: bool add_row(tools::impi& a_mpi,int a_dest,int a_tag) { if(m_cols.empty()) return false; tools_vforit(tools::wroot::icol*,m_cols,it) (*it)->add(); tools::uint32 icol = 0; tools_vforit(tools::wroot::icol*,m_cols,it) { basket_add _badd(m_file,a_mpi,a_dest,a_tag,icol);icol++; if(!(*it)->get_branch()->pfill(_badd)) return false; } tools_vforit(tools::wroot::icol*,m_cols,it) (*it)->set_def(); return true; } protected: void end_leaves(std::vector& a_lengths,std::vector& a_mxs) const { a_lengths.clear(); a_mxs.clear(); tools_vforcit(tools::wroot::icol*,m_cols,it) { tools::wroot::base_leaf* _leaf = (*it)->get_leaf(); tools::wroot::leaf_string* _leafs = _leaf?tools::id_cast(*_leaf):0; if(_leafs) { a_lengths.push_back(_leafs->length()); a_mxs.push_back(_leafs->get_max()); } } } public: bool end_fill(tools::impi& a_mpi,int a_dest,int a_tag) { tools::uint32 icol = 0; tools_vforit(tools::wroot::icol*,m_cols,it) { basket_add _badd(m_file,a_mpi,a_dest,a_tag,icol);icol++; if(!(*it)->get_branch()->end_pfill(_badd)) return false; } std::vector lengths; std::vector mxs; end_leaves(lengths,mxs); a_mpi.pack_reset(); if(!a_mpi.pack(protocol_end_fill())) return false; if(!a_mpi.vpack(lengths)) return false; if(!a_mpi.vpack(mxs)) return false; if(!a_mpi.send_buffer(a_dest,a_tag)) return false; return true; } protected: }; inline tools::wroot::basket* get_basket(std::ostream& a_out,tools::impi& a_mpi, bool a_byte_swap,tools::wroot::seek a_seek_directory, tools::uint32 a_basket_size) { std::string oname; if(!a_mpi.sunpack(oname)) return 0; std::string otitle; if(!a_mpi.sunpack(otitle)) return 0; tools::uint32 last,nev_buf_size,nev; if(!a_mpi.unpack(last)) return 0; if(!a_mpi.unpack(nev_buf_size)) return 0; if(!a_mpi.unpack(nev)) return 0; int* entry_offset = 0; {bool not_null; if(!a_mpi.bunpack(not_null)) return 0; if(not_null) { tools::uint32 n; if(!a_mpi.unpack(n,entry_offset)) return 0; }} int* displacement = 0; {bool not_null; if(!a_mpi.bunpack(not_null)) return 0; if(not_null) { tools::uint32 n; if(!a_mpi.unpack(n,displacement)) return 0; }} tools::uint32 _size; char* _buffer; if(!a_mpi.unpack(_size,_buffer)) {a_out << "unpack(buffer) failed."<< std::endl;return 0;} // wbasket fields set at file writing : //m_buf_size,m_buffer,m_nbytes,m_object_size,m_date,m_cycle,m_seek_key //::printf("debug : col = %d, %s, %s, %lu\n", // icol,rbasket.object_class().c_str(),rbasket.object_name().c_str(),rbasket.seek_key()); tools::wroot::basket* basket = new tools::wroot::basket(a_out,a_byte_swap,a_seek_directory, oname,otitle,"TBasket",a_basket_size, false/*verbose*/); basket->datbuf().write_fast_array(_buffer,_size); basket->set_nev(last,nev_buf_size,nev,entry_offset,displacement); delete [] _buffer; return basket; } }} #endif