// CompoundDatasetMerger.cxx #include "dataset_split/CompoundDatasetMerger.h" #include #include "dataset_util/WorkingDirectory.h" #include "dataset_base/SimpleCompoundDataset.h" #include "dataset_split/DatasetMergeResult.h" using std::string; using std::ostream; using std::cerr; using std::endl; using std::auto_ptr; using dset::Dataset; using dset::DatasetList; using dset::SimpleCompoundDataset; using dset::DatasetMergeResult; using dset::CompoundDatasetMerger; //********************************************************************** // Local definitions. //********************************************************************** namespace { // Empty result. const DatasetMergeResult& empty_result() { static DatasetMergeResult badres; return badres; } } // end unnamed namespace //********************************************************************** // Member functions //********************************************************************** // Constructor. CompoundDatasetMerger::CompoundDatasetMerger(string dir) : m_dir(dir), m_err(0), m_pmrg(0), m_pdst(), m_pres(0), m_open(true), m_update_result(false) { const DatasetList empty; WorkingDirectory wd(m_dir); m_pres = new DatasetMergeResult(empty, empty, empty, 0); } //********************************************************************** // Destructor. CompoundDatasetMerger::~CompoundDatasetMerger() { WorkingDirectory wd(m_dir); delete m_pmrg; for ( MergerList::iterator imrg=m_mrgs.begin(); imrg!=m_mrgs.end(); ++imrg ) { delete *imrg; } delete m_pres; delete m_pdst; } //********************************************************************** // Validity. bool CompoundDatasetMerger::is_valid() const { return error() == 0; } //********************************************************************** // Open. bool CompoundDatasetMerger::is_open() const { return is_valid() && m_open; } //********************************************************************** // Append. int CompoundDatasetMerger::append(const Dataset& dst) { if ( error() ) return 300; if ( ! is_open() ) return 301; if ( ! dst.is_valid() ) return set_error(302); WorkingDirectory wd(m_dir); // First call, create the sub-dataset mergers. if ( m_pmrg == 0 && m_mrgs.size()==0 ) { const SimpleCompoundDataset* pscdst = dynamic_cast(&dst); // Input is not compound: create a single merger. if ( pscdst == 0 ) { m_pmrg = new DefaultDatasetMerger(m_dir); int stat = m_pmrg->append(dst); if ( stat ) { return set_error(3100+stat); } // Input is compound: create a merger for each constituent. } else { const DatasetList& dsts = pscdst->constituents(); for ( DatasetList::const_iterator idst=dsts.begin(); idst!=dsts.end(); ++idst ) { if ( *idst == 0 ) { cerr << "CompoundDatasetMerger::append: " << "Input subdataset is null" << endl; return set_error(304); } m_mrgs.push_back(new DefaultDatasetMerger(m_dir)); int stat = m_mrgs.back()->append(**idst); if ( stat != 0 ) { return set_error(3200 + stat); } } } // Other calls, append to the existing merger(s). } else { // No constituents. if ( m_pmrg != 0 ) { int stat = m_pmrg->append(dst); if ( stat != 0 ) { return set_error(3300 + stat); } // Constituents. } else { const SimpleCompoundDataset* pscdst = dynamic_cast(&dst); if ( pscdst == 0 ) { return set_error(312); } const DatasetList& dsts = pscdst->constituents(); if ( dsts.size() != m_mrgs.size() ) { return set_error(313); } DatasetList::const_iterator idst = dsts.begin(); for ( MergerList::iterator imrg=m_mrgs.begin(); imrg!=m_mrgs.end(); ++imrg ) { if ( *idst == 0 ) { return set_error(314); } DefaultDatasetMerger& merg = **imrg; if ( *imrg == 0 ) { return set_error(314); } const Dataset& dst = **idst; DatasetMerger& mrg = **imrg; int stat = mrg.append(dst); if ( stat != 0 ) { return set_error(3400+stat); } assert( idst != dsts.end() ); ++idst; } assert( idst == dsts.end() ); } } m_update_result = true; m_dsts.push_back(&dst); return set_error(0); } //********************************************************************** // Return the result. DatasetMergeResult CompoundDatasetMerger::result() { if ( error() ) { return DatasetMergeResult(error()); } if ( ! is_open() ) { if ( m_pres == 0 ) { return empty_result(); } return *m_pres; } if ( m_pmrg == 0 && m_mrgs.size()==0 ) { if ( m_pres == 0 ) { return empty_result(); } return *m_pres; } WorkingDirectory wd(m_dir); // If result needs to be updated, do so. if ( m_update_result ) { // Delete the old result. delete m_pdst; delete m_pres; m_pdst = 0; m_pres = 0; // Merge is not a SimpleCompoundDataset use a singe default merger. if ( m_pmrg != 0 ) { m_pres = new DatasetMergeResult(m_pmrg->result()); // Merge is a SimpleCompoundDataset. } else { if ( m_mrgs.size() == 0 ) { return DatasetMergeResult(set_error(323)); } Dataset* pscdst = new SimpleCompoundDataset; for ( MergerList::iterator imrg=m_mrgs.begin(); imrg!=m_mrgs.end(); ++imrg ) { DatasetMerger& mrg = **imrg; const DatasetMergeResult& res = mrg.result(); if ( ! res.is_valid() ) { return DatasetMergeResult(set_error(323)); } const Dataset* pdst = res.dataset(); if ( pdst == 0 ) { return DatasetMergeResult(set_error(325)); } if ( ! pdst->is_valid() ) { return DatasetMergeResult(set_error(326)); } int stat = pscdst->merge(*pdst); if ( stat ) { return DatasetMergeResult(set_error(3500+stat)); } } pscdst->lock(); m_pdst = pscdst; const DatasetList rdsts; m_pres = new DatasetMergeResult(m_dsts, m_dsts, rdsts, m_pdst); } m_update_result = false; } return *m_pres; } //********************************************************************** // Close. int CompoundDatasetMerger::close() { WorkingDirectory wd(m_dir); // Pass call on to the constituent mergers. if ( m_pmrg != 0 ) { assert( m_mrgs.size() == 0 ); m_pmrg->close(); } else { for (MergerList::iterator imrg=m_mrgs.begin(); imrg!=m_mrgs.end(); ++imrg ) { DatasetMerger& mrg = **imrg; mrg.close(); } } // Release the result dataset. if ( m_pdst != 0 ) { m_pdst->release(); } // Mark result closed. m_open = false; return 0; } //********************************************************************** // Set error code. int CompoundDatasetMerger::set_error(int err) { m_err = err; return err; } //********************************************************************** // Return the error code. int CompoundDatasetMerger::error() const { return m_err; } //********************************************************************** // Output stream. ostream& CompoundDatasetMerger::ostr(std::ostream& str) const { if ( ! is_valid() ) { str << "Invalid default dataset merger"; } else { int count = m_dsts.size(); str << "Compound dataset merger with " << count << " datasets"; if ( count != 1 ) str << "s"; } return str; } //**********************************************************************