From e944442793d11bb08403b5c0fe60bd107829a084 Mon Sep 17 00:00:00 2001 From: Andre Mueller Date: Mon, 9 Mar 2020 10:25:15 +0100 Subject: [PATCH] fixed problem with g++5 'this' capture; better database h/cpp separation --- Makefile | 10 +- src/candidates.h | 2 +- src/classification.cpp | 2 +- src/database.cpp | 346 ++++++++++++++++++++++++++ src/{sketch_database.h => database.h} | 269 +------------------- src/mode_build.cpp | 2 +- src/mode_info.cpp | 2 +- src/options.cpp | 2 +- src/printing.cpp | 4 +- src/querying.h | 2 +- src/sketch_database.cpp | 58 ----- src/version.h | 2 +- 12 files changed, 371 insertions(+), 330 deletions(-) create mode 100644 src/database.cpp rename src/{sketch_database.h => database.h} (78%) delete mode 100644 src/sketch_database.cpp diff --git a/Makefile b/Makefile index b59d9b4..362e7d3 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,7 @@ HEADERS = \ src/classification_statistics.h \ src/cmdline_utility.h \ src/config.h \ + src/database.h \ src/dna_encoding.h \ src/filesys_utility.h \ src/hash_dna.h \ @@ -43,7 +44,6 @@ HEADERS = \ src/querying.h \ src/sequence_io.h \ src/sequence_view.h \ - src/sketch_database.h \ src/stat_confusion.h \ src/stat_moments.h \ src/string_utils.h \ @@ -55,6 +55,7 @@ HEADERS = \ SOURCES = \ src/classification.cpp \ src/cmdline_utility.cpp \ + src/database.cpp \ src/filesys_utility.cpp \ src/main.cpp \ src/mode_build.cpp \ @@ -65,7 +66,6 @@ SOURCES = \ src/options.cpp \ src/printing.cpp \ src/sequence_io.cpp \ - src/sketch_database.cpp \ src/taxonomy_io.cpp @@ -143,7 +143,7 @@ $(REL_DIR)/mode_query.o : src/mode_query.cpp $(HEADERS) $(REL_DIR)/taxonomy_io.o : src/taxonomy_io.cpp $(HEADERS) $(REL_COMPILE) -$(REL_DIR)/sketch_database.o : src/sketch_database.cpp $(HEADERS) +$(REL_DIR)/database.o : src/database.cpp $(HEADERS) $(REL_COMPILE) $(REL_DIR)/options.o : src/options.cpp $(HEADERS) @@ -195,7 +195,7 @@ $(DBG_DIR)/mode_query.o : src/mode_query.cpp $(HEADERS) $(DBG_DIR)/taxonomy_io.o : src/taxonomy_io.cpp $(HEADERS) $(DBG_COMPILE) -$(DBG_DIR)/sketch_database.o : src/sketch_database.cpp $(HEADERS) +$(DBG_DIR)/database.o : src/database.cpp $(HEADERS) $(DBG_COMPILE) $(DBG_DIR)/options.o : src/options.cpp $(HEADERS) @@ -247,7 +247,7 @@ $(PRF_DIR)/mode_query.o : src/mode_query.cpp $(HEADERS) $(PRF_DIR)/taxonomy_io.o : src/taxonomy_io.cpp $(HEADERS) $(PRF_COMPILE) -$(PRF_DIR)/sketch_database.o : src/sketch_database.cpp $(HEADERS) +$(PRF_DIR)/database.o : src/database.cpp $(HEADERS) $(PRF_COMPILE) $(PRF_DIR)/options.o : src/options.cpp $(HEADERS) diff --git a/src/candidates.h b/src/candidates.h index 6f93270..44a6e69 100644 --- a/src/candidates.h +++ b/src/candidates.h @@ -27,7 +27,7 @@ #include #include -#include "sketch_database.h" +#include "database.h" namespace mc { diff --git a/src/classification.cpp b/src/classification.cpp index 12cbe9d..c28f5a2 100644 --- a/src/classification.cpp +++ b/src/classification.cpp @@ -39,7 +39,7 @@ #include "querying.h" #include "sequence_io.h" #include "sequence_view.h" -#include "sketch_database.h" +#include "database.h" #include "classification.h" diff --git a/src/database.cpp b/src/database.cpp new file mode 100644 index 0000000..1bf21b7 --- /dev/null +++ b/src/database.cpp @@ -0,0 +1,346 @@ +/****************************************************************************** + * + * MetaCache - Meta-Genomic Classification Tool + * + * Copyright (C) 2016-2020 André Müller (muellan@uni-mainz.de) + * & Robin Kobus (kobus@uni-mainz.de) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *****************************************************************************/ + +#include "database.h" + + +namespace mc { + + +// ---------------------------------------------------------------------------- +bool database::add_target(const sequence& seq, taxon_name sid, + taxon_id parentTaxid, + file_source source) +{ + using std::begin; + using std::end; + + //reached hard limit for number of targets + if(targets_.size() >= max_target_count()) { + throw target_limit_exceeded_error{}; + } + + if(seq.empty()) return false; + + //don't allow non-unique sequence ids + if(name2tax_.find(sid) != name2tax_.end()) return false; + + const auto targetCount = target_id(targets_.size()); + const auto taxid = taxon_id_of_target(targetCount); + + //sketch sequence -> insert features + source.windows = add_all_window_sketches(seq, targetCount); + + //insert sequence metadata as a new taxon + if(parentTaxid < 1) parentTaxid = 0; + auto nit = taxa_.emplace( + taxid, parentTaxid, sid, + taxon_rank::Sequence, std::move(source)); + + //should never happen + if(nit == taxa_.end()) { + throw std::runtime_error{"target taxon could not be created"}; + } + + //allows lookup via sequence id (e.g. NCBI accession number) + const taxon* newtax = &(*nit); + name2tax_.insert({std::move(sid), newtax}); + + //target id -> taxon lookup table + targets_.push_back(newtax); + + targetLineages_.mark_outdated(); + + return true; +} + + + +// ---------------------------------------------------------------------------- +void database::read(const std::string& filename, scope what) + +{ + std::ifstream is{filename, std::ios::in | std::ios::binary}; + + if(!is.good()) { + throw file_access_error{"can't open file " + filename}; + } + + //database version info + using std::uint64_t; + using std::uint8_t; + uint64_t dbVer = 0; + read_binary(is, dbVer); + + if(uint64_t( MC_DB_VERSION ) != dbVer) { + throw file_read_error{ + "Database " + filename + " (version " + std::to_string(dbVer) + ")" + + " is incompatible\nwith this version of MetaCache" + + " (uses version " + std::to_string(MC_DB_VERSION) + ")" }; + } + + //data type info + { + //data type widths + uint8_t featureSize = 0; read_binary(is, featureSize); + uint8_t targetSize = 0; read_binary(is, targetSize); + uint8_t windowSize = 0; read_binary(is, windowSize); + uint8_t bucketSize = 0; read_binary(is, bucketSize); + uint8_t taxidSize = 0; read_binary(is, taxidSize); + uint8_t numTaxRanks = 0; read_binary(is, numTaxRanks); + + if( (sizeof(feature) != featureSize) || + (sizeof(target_id) != targetSize) || + (sizeof(bucket_size_type) != bucketSize) || + (sizeof(window_id) != windowSize) ) + { + throw file_read_error{ + "Database " + filename + + " is incompatible with this variant of MetaCache" + + " due to different data type sizes"}; + } + + if( (sizeof(taxon_id) != taxidSize) || + (taxonomy::num_ranks != numTaxRanks) ) + { + throw file_read_error{ + "Database " + filename + + " is incompatible with this variant of MetaCache" + + " due to different taxonomy data types"}; + } + } + + clear(); + + //sketching parameters + read_binary(is, targetSketcher_); + read_binary(is, querySketcher_); + + //target insertion parameters + read_binary(is, maxLocsPerFeature_); + + //taxon metadata + read_binary(is, taxa_); + + target_id targetCount = 0; + read_binary(is, targetCount); + if(targetCount < 1) return; + + //update target id -> target taxon lookup table + targets_.reserve(targetCount); + for(decltype(targetCount) i = 0 ; i < targetCount; ++i) { + targets_.push_back(taxa_[taxon_id_of_target(i)]); + } + + //sequence id lookup + name2tax_.clear(); + for(const auto& t : taxa_) { + if(t.rank() == taxon_rank::Sequence) { + name2tax_.insert({t.name(), &t}); + } + } + + mark_cached_lineages_outdated(); + update_cached_lineages(taxon_rank::Sequence); + + if(what == scope::metadata_only) return; + + //hash table + read_binary(is, features_); +} + + + +// ---------------------------------------------------------------------------- +void database::write(const std::string& filename) const +{ + using std::uint64_t; + using std::uint8_t; + + std::ofstream os{filename, std::ios::out | std::ios::binary}; + + if(!os.good()) { + throw file_access_error{"can't open file " + filename}; + } + + //database version info + write_binary(os, uint64_t( MC_DB_VERSION )); + + //data type widths + write_binary(os, uint8_t(sizeof(feature))); + write_binary(os, uint8_t(sizeof(target_id))); + write_binary(os, uint8_t(sizeof(window_id))); + write_binary(os, uint8_t(sizeof(bucket_size_type))); + write_binary(os, uint8_t(sizeof(taxon_id))); + write_binary(os, uint8_t(taxonomy::num_ranks)); + + //sketching parameters + write_binary(os, targetSketcher_); + write_binary(os, querySketcher_); + + //target insertion parameters + write_binary(os, maxLocsPerFeature_); + + //taxon & target metadata + write_binary(os, taxa_); + write_binary(os, target_id(targets_.size())); + + //hash table + write_binary(os, features_); +} + + + +// ---------------------------------------------------------------------------- +void database::max_locations_per_feature(bucket_size_type n) +{ + if(n < 1) n = 1; + if(n >= max_supported_locations_per_feature()) { + n = max_supported_locations_per_feature(); + } + else if(n < maxLocsPerFeature_) { + for(auto i = features_.begin(), e = features_.end(); i != e; ++i) { + if(i->size() > n) features_.shrink(i, n); + } + } + maxLocsPerFeature_ = n; +} + + + +// ---------------------------------------------------------------------------- +database::feature_count_type +database::remove_features_with_more_locations_than(bucket_size_type n) +{ + //note that features are not really removed, because the hashmap + //does not support erasing keys; instead all values belonging to + //the key are cleared and the key is kept without values + feature_count_type rem = 0; + for(auto i = features_.begin(), e = features_.end(); i != e; ++i) { + if(i->size() > n) { + features_.clear(i); + ++rem; + } + } + return rem; +} + + + +// ---------------------------------------------------------------------------- +database::feature_count_type +database::remove_ambiguous_features(taxon_rank r, bucket_size_type maxambig) +{ + feature_count_type rem = 0; + + if(taxa_.empty()) { + throw std::runtime_error{"no taxonomy available!"}; + } + + if(maxambig == 0) maxambig = 1; + + if(r == taxon_rank::Sequence) { + for(auto i = features_.begin(), e = features_.end(); i != e; ++i) { + if(!i->empty()) { + std::set targets; + for(auto loc : *i) { + targets.insert(loc.tgt); + if(targets.size() > maxambig) { + features_.clear(i); + ++rem; + break; + } + } + } + } + } + else { + for(auto i = features_.begin(), e = features_.end(); i != e; ++i) { + if(!i->empty()) { + std::set taxa; + for(auto loc : *i) { + taxa.insert(targetLineages_[loc.tgt][int(r)]); + if(taxa.size() > maxambig) { + features_.clear(i); + ++rem; + break; + } + } + } + } + } + return rem; +} + + + +// ---------------------------------------------------------------------------- +void database::clear() { + ranksCache_.clear(); + targetLineages_.clear(); + name2tax_.clear(); + features_.clear(); +} + + +// ---------------------------------------------------------------------------- +/** + * @brief very dangerous! clears feature map without memory deallocation + */ +void database::clear_without_deallocation() { + ranksCache_.clear(); + targetLineages_.clear(); + name2tax_.clear(); + features_.clear_without_deallocation(); +} + + + + +// ---------------------------------------------------------------------------- +database +make_database(const std::string& filename, database::scope what, info_level info) +{ + if(filename.empty()) throw file_access_error{"No database name given"}; + + database db; + + const bool showInfo = info != info_level::silent; + + if(showInfo) { + std::cerr << "Reading database from file '" + << filename << "' ... " << std::flush; + } + try { + db.read(filename, what); + if(showInfo) std::cerr << "done." << std::endl; + } + catch(const file_access_error& e) { + std::cerr << "FAIL" << std::endl; + throw file_access_error{"Could not read database file '" + filename + "'"}; + } + + return db; +} + + +} // namespace mc diff --git a/src/sketch_database.h b/src/database.h similarity index 78% rename from src/sketch_database.h rename to src/database.h index dfc47da..236512e 100644 --- a/src/sketch_database.h +++ b/src/database.h @@ -341,19 +341,8 @@ class database //--------------------------------------------------------------- - void max_locations_per_feature(bucket_size_type n) - { - if(n < 1) n = 1; - if(n >= max_supported_locations_per_feature()) { - n = max_supported_locations_per_feature(); - } - else if(n < maxLocsPerFeature_) { - for(auto i = features_.begin(), e = features_.end(); i != e; ++i) { - if(i->size() > n) features_.shrink(i, n); - } - } - maxLocsPerFeature_ = n; - } + void max_locations_per_feature(bucket_size_type); + //----------------------------------------------------- bucket_size_type max_locations_per_feature() const noexcept { @@ -367,20 +356,7 @@ class database //----------------------------------------------------- feature_count_type - remove_features_with_more_locations_than(bucket_size_type n) - { - //note that features are not really removed, because the hashmap - //does not support erasing keys; instead all values belonging to - //the key are cleared and the key is kept without values - feature_count_type rem = 0; - for(auto i = features_.begin(), e = features_.end(); i != e; ++i) { - if(i->size() > n) { - features_.clear(i); - ++rem; - } - } - return rem; - } + remove_features_with_more_locations_than(bucket_size_type); //--------------------------------------------------------------- @@ -392,96 +368,14 @@ class database * @return number of features (hash table buckets) that were removed */ feature_count_type - remove_ambiguous_features(taxon_rank r, bucket_size_type maxambig) - { - feature_count_type rem = 0; - - if(taxa_.empty()) { - throw std::runtime_error{"no taxonomy available!"}; - } - - if(maxambig == 0) maxambig = 1; - - if(r == taxon_rank::Sequence) { - for(auto i = features_.begin(), e = features_.end(); i != e; ++i) { - if(!i->empty()) { - std::set targets; - for(auto loc : *i) { - targets.insert(loc.tgt); - if(targets.size() > maxambig) { - features_.clear(i); - ++rem; - break; - } - } - } - } - } - else { - for(auto i = features_.begin(), e = features_.end(); i != e; ++i) { - if(!i->empty()) { - std::set taxa; - for(auto loc : *i) { - taxa.insert(targetLineages_[loc.tgt][int(r)]); - if(taxa.size() > maxambig) { - features_.clear(i); - ++rem; - break; - } - } - } - } - } - return rem; - } + remove_ambiguous_features(taxon_rank, bucket_size_type maxambig); //--------------------------------------------------------------- bool add_target(const sequence& seq, taxon_name sid, taxon_id parentTaxid = 0, - file_source source = file_source{}) - { - using std::begin; - using std::end; - - //reached hard limit for number of targets - if(targets_.size() >= max_target_count()) { - throw target_limit_exceeded_error{}; - } + file_source source = file_source{}); - if(seq.empty()) return false; - - //don't allow non-unique sequence ids - if(name2tax_.find(sid) != name2tax_.end()) return false; - - const auto targetCount = target_id(targets_.size()); - const auto taxid = taxon_id_of_target(targetCount); - - //sketch sequence -> insert features - source.windows = add_all_window_sketches(seq, targetCount); - - //insert sequence metadata as a new taxon - if(parentTaxid < 1) parentTaxid = 0; - auto nit = taxa_.emplace( - taxid, parentTaxid, sid, - taxon_rank::Sequence, std::move(source)); - - //should never happen - if(nit == taxa_.end()) { - throw std::runtime_error{"target taxon could not be created"}; - } - - //allows lookup via sequence id (e.g. NCBI accession number) - const taxon* newtax = &(*nit); - name2tax_.insert({std::move(sid), newtax}); - - //target id -> taxon lookup table - targets_.push_back(newtax); - - targetLineages_.mark_outdated(); - - return true; - } //--------------------------------------------------------------- @@ -505,24 +399,12 @@ class database //--------------------------------------------------------------- - void clear() { - ranksCache_.clear(); - targetLineages_.clear(); - name2tax_.clear(); - features_.clear(); - } + void clear(); - - //----------------------------------------------------- /** * @brief very dangerous! clears feature map without memory deallocation */ - void clear_without_deallocation() { - ranksCache_.clear(); - targetLineages_.clear(); - name2tax_.clear(); - features_.clear_without_deallocation(); - } + void clear_without_deallocation(); //--------------------------------------------------------------- @@ -796,8 +678,6 @@ class database return 0.8f; } - - //--------------------------------------------------------------- /** * @brief read database from binary file * @details Note that the map is not just de-serialized but @@ -805,138 +685,11 @@ class database * This should make DB files more robust against changes in the * internal mapping structure. */ - void read(const std::string& filename, scope what = scope::everything) - { - std::ifstream is{filename, std::ios::in | std::ios::binary}; - - if(!is.good()) { - throw file_access_error{"can't open file " + filename}; - } - - //database version info - using std::uint64_t; - using std::uint8_t; - uint64_t dbVer = 0; - read_binary(is, dbVer); - - if(uint64_t( MC_DB_VERSION ) != dbVer) { - throw file_read_error{ - "Database " + filename + " (version " + std::to_string(dbVer) + ")" - + " is incompatible\nwith this version of MetaCache" - + " (uses version " + std::to_string(MC_DB_VERSION) + ")" }; - } - - //data type info - { - //data type widths - uint8_t featureSize = 0; read_binary(is, featureSize); - uint8_t targetSize = 0; read_binary(is, targetSize); - uint8_t windowSize = 0; read_binary(is, windowSize); - uint8_t bucketSize = 0; read_binary(is, bucketSize); - uint8_t taxidSize = 0; read_binary(is, taxidSize); - uint8_t numTaxRanks = 0; read_binary(is, numTaxRanks); - - if( (sizeof(feature) != featureSize) || - (sizeof(target_id) != targetSize) || - (sizeof(bucket_size_type) != bucketSize) || - (sizeof(window_id) != windowSize) ) - { - throw file_read_error{ - "Database " + filename + - " is incompatible with this variant of MetaCache" + - " due to different data type sizes"}; - } - - if( (sizeof(taxon_id) != taxidSize) || - (taxonomy::num_ranks != numTaxRanks) ) - { - throw file_read_error{ - "Database " + filename + - " is incompatible with this variant of MetaCache" + - " due to different taxonomy data types"}; - } - } - - clear(); - - //sketching parameters - read_binary(is, targetSketcher_); - read_binary(is, querySketcher_); - - //target insertion parameters - read_binary(is, maxLocsPerFeature_); - - //taxon metadata - read_binary(is, taxa_); - - target_id targetCount = 0; - read_binary(is, targetCount); - if(targetCount < 1) return; - - //update target id -> target taxon lookup table - targets_.reserve(targetCount); - for(decltype(targetCount) i = 0 ; i < targetCount; ++i) { - targets_.push_back(taxa_[taxon_id_of_target(i)]); - } - - //sequence id lookup - name2tax_.clear(); - for(const auto& t : taxa_) { - if(t.rank() == taxon_rank::Sequence) { - name2tax_.insert({t.name(), &t}); - } - } - - mark_cached_lineages_outdated(); - update_cached_lineages(taxon_rank::Sequence); - - if(what == scope::metadata_only) return; - - //hash table - read_binary(is, features_); - } - - - //------------------------------------------------------------------- + void read(const std::string& filename, scope what = scope::everything); /** * @brief write database to binary file */ - void write(const std::string& filename) const - { - using std::uint64_t; - using std::uint8_t; - - std::ofstream os{filename, std::ios::out | std::ios::binary}; - - if(!os.good()) { - throw file_access_error{"can't open file " + filename}; - } - - //database version info - write_binary(os, uint64_t( MC_DB_VERSION )); - - //data type widths - write_binary(os, uint8_t(sizeof(feature))); - write_binary(os, uint8_t(sizeof(target_id))); - write_binary(os, uint8_t(sizeof(window_id))); - write_binary(os, uint8_t(sizeof(bucket_size_type))); - write_binary(os, uint8_t(sizeof(taxon_id))); - write_binary(os, uint8_t(taxonomy::num_ranks)); - - //sketching parameters - write_binary(os, targetSketcher_); - write_binary(os, querySketcher_); - - //target insertion parameters - write_binary(os, maxLocsPerFeature_); - - //taxon & target metadata - write_binary(os, taxa_); - write_binary(os, target_id(targets_.size())); - - //hash table - write_binary(os, features_); - } + void write(const std::string& filename) const; //--------------------------------------------------------------- @@ -1055,8 +808,8 @@ class database execOpt.concurrency(1); inserter_ = std::make_unique>( execOpt, - [&](int, const auto& batch) { - add_sketch_batch(batch); + [&,this](int, const auto& batch) { + this->add_sketch_batch(batch); }); } diff --git a/src/mode_build.cpp b/src/mode_build.cpp index b74ba60..5c54a3d 100644 --- a/src/mode_build.cpp +++ b/src/mode_build.cpp @@ -39,7 +39,7 @@ #include "filesys_utility.h" #include "io_error.h" #include "io_options.h" -#include "sketch_database.h" +#include "database.h" #include "printing.h" #include "sequence_io.h" #include "taxonomy_io.h" diff --git a/src/mode_info.cpp b/src/mode_info.cpp index 3990d3e..5177f7a 100644 --- a/src/mode_info.cpp +++ b/src/mode_info.cpp @@ -29,7 +29,7 @@ #include "options.h" #include "candidates.h" -#include "sketch_database.h" +#include "database.h" #include "printing.h" #include "typename.h" diff --git a/src/options.cpp b/src/options.cpp index ed4de2e..bf04d8d 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -38,7 +38,7 @@ #include "options.h" #include "filesys_utility.h" -#include "sketch_database.h" +#include "database.h" #include "../dep/clipp.h" diff --git a/src/printing.cpp b/src/printing.cpp index 4e2a0da..411d99f 100644 --- a/src/printing.cpp +++ b/src/printing.cpp @@ -23,12 +23,12 @@ #include #include -#include "sketch_database.h" +#include "database.h" #include "candidates.h" #include "classification.h" #include "classification_statistics.h" #include "matches_per_target.h" -#include "sketch_database.h" +#include "database.h" #include "stat_confusion.h" #include "taxonomy.h" #include "options.h" diff --git a/src/querying.h b/src/querying.h index 26f6135..eccd7f7 100644 --- a/src/querying.h +++ b/src/querying.h @@ -26,7 +26,7 @@ #include #include -#include "sketch_database.h" +#include "database.h" #include "options.h" #include "sequence_io.h" #include "cmdline_utility.h" diff --git a/src/sketch_database.cpp b/src/sketch_database.cpp deleted file mode 100644 index 28473aa..0000000 --- a/src/sketch_database.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/****************************************************************************** - * - * MetaCache - Meta-Genomic Classification Tool - * - * Copyright (C) 2016-2020 André Müller (muellan@uni-mainz.de) - * & Robin Kobus (kobus@uni-mainz.de) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - *****************************************************************************/ - -#include "sketch_database.h" - - -namespace mc { - - -// ---------------------------------------------------------------------------- -database -make_database(const std::string& filename, database::scope what, info_level info) -{ - if(filename.empty()) throw file_access_error{"No database name given"}; - - database db; - - const bool showInfo = info != info_level::silent; - - if(showInfo) { - std::cerr << "Reading database from file '" - << filename << "' ... " << std::flush; - } - try { - db.read(filename, what); - if(showInfo) std::cerr << "done." << std::endl; - } - catch(const file_access_error& e) { - std::cerr << "FAIL" << std::endl; - throw file_access_error{"Could not read database file '" + filename + "'"}; - } - - return db; -} - - - - -} // namespace mc diff --git a/src/version.h b/src/version.h index 9f8bfe9..d3aa4fa 100644 --- a/src/version.h +++ b/src/version.h @@ -28,7 +28,7 @@ #define MC_DB_VERSION 20191115 -#define MC_VERSION_STRING "1.1.0" +#define MC_VERSION_STRING "1.1.1" #endif